i++,++i的讨论引题
临时对象都是右值
//临时对象
//i++,右值,会产生一个临时对象,
//如何保存这个临时对象
int i = 0;
int&& saveI = i++;//这样写的话,这个临时变量就会一直保存到程序结束,saveI和i之间没有什么关系
为什么减少临时变量能提升系统效率呢?
要知道临时对象
是存贮在栈
中的,如果写代码的时候能减少临时变量的产生,将会提升系统的效率
一:产生临时对象的情况和解决方案
1、以传值的方式给函数传递参数,这个用得太多了,所以就不举例说明了
2、类型转换生成的临时对象 / 隐式类型转换以保证函数调用成功
2.1 类型转换生成的临时对象
class classA
{
public:
int val1;
int val2;
public:
classA(int a = 1, int b = 2);
classA(const classA& obj);
virtual ~classA();
classA& operator=(const classA& obj);
};
classA::classA(int a, int b) :val1(a), val2(b)
{
cout << "调用了构造函数" << endl;
cout << "val1 = " << val1 << endl;
cout << "val2 = " << val2 << endl;
}
classA::classA(const classA& obj)
{
cout << "调用了拷贝函数" << endl;
val1 = obj.val1;
val2 = obj.val2;
}
classA::~classA()
{
cout << "调用了析构函数" << endl;
}
classA& classA::operator=(const classA& obj)
{
cout << "调用了赋值运算符" << endl;
val1 = obj.val1;
val2 = obj.val2;
return *this;
}
int main()
{
classA myClassA;
myClassA = 1000;//这一步用的是赋值运算符
}
运行结果:
可以看出,就这一个“=”号就做了三件事情
- 1、执行了构造函数,创建了一个临时变量
- 2、执行了赋值运算符,将值传递给对象
- 3、执行了析构函数
这样系统白白多执行了三个步骤
我们如何改进呢?
最好初始化的时候就赋值,这样就不会生成临时变量
classA myClassA = 1000;
执行效果如下
2.2 隐式类型转换以保证函数调用成功
//可以看到,传递进来的参数是char数组,而接收却用的是const string&
//这里系统就会直接进行隐式类型转换
//那么可不可以用string& 来接收呢?
//那肯定是不行的,正面理解比较困难,我们反着理解
//如果你用了string& sourceStr 来接收,系统会认为你有权限去改变sourceStr
//但是这个string是系统给你构造的临时变量,不会造成原先char数组的改变,系统为了防止你无意中犯下这个错误
//编译的时候就会告诉你出错
//系统会为const string& sourceStr构造临时变量
//但是不会为string& sourceStr构造临时变量
int testMethod1(const string& sourceStr, char x)
{
const char* p = sourceStr.c_str();
int count = 0;
//todo
return count;
}
int main()
{
char myCharArray[100] = "I Love You";
int result = testMethod1(myCharArray, 'o');
cout << result << endl;
}
3、函数返回对象的时候
classA testMethod2(classA& obj)
{
classA myNewClassA;
myNewClassA.val1 = obj.val1;
myNewClassA.val2 = obj.val2;
return myNewClassA;
}
int main()
{
classA myClassB;
testMethod2(myClassB);
}
这里return myNewClassA
的时候,也会创造一个临时变量
执行效果如下:可以看出,我们只显式声明了两个对象,可是却调用了三次析构函数,一次拷贝构造函数,可以得出结论:
return myNewClassA
的时候,会创造一个临时变量
那么如何改进呢?
classA testMethod2(classA& obj)
{
return classA(obj.val1, obj.val2);//这样就不会构造临时对象了
}
int main()
{
classA myClassB;
//这里直接接收返回的对象,会保存函数内部创建的对象
classA myNewClassB = testMethod2(myClassB);
}
执行效果如下:
二:类外运算符重载
class testclass
{
public:
testclass(int a = 0, int b = 0) :a(a), b(b) {};
public:
int a;
int b;
};
//这是经过优化过临时变量的类外运算符重载
testclass operator+(testclass& class1, testclass& class2)
{
return testclass(class1.a + class2.a, class1.b + class2.b);
}
int main()
{
testclass class1(1, 2);
testclass class2(1, 2);
testclass class3 = class1 + class2;
cout << class3.a << endl;
cout << class3.b << endl;
return 0
}
运行结果如下: