一、临时对象的概念
临时对象 就是因为一些原因,系统需要一个对象来保存状态等等 隐式的创建一个对象 用后立刻析构。临时对象都是无名的,也就是不是显式的 这个是为了写代码方便,少写一点,系统帮你干的活。 但有时,如果构造和析构写的不够好,临时对象的产生 以及销毁 就会引起程序错误了。
int i = 1;
i++;//先产生临时变量,然后i+1,再返回这个临时变量
int &&r1 = i++; //右值引用绑定右值,这里的i和r1没有任何关系
r1 = 19;
i = 100;
二、产生临时对象的情况和解决
这里主要是针对代码书写产生的临时变量
class tempClass {
public:
tempClass(int tempnum1 = 0,int tempnum2 = 0);
tempClass(const tempClass & temp):num1(temp.num1),num2(temp.num2) {
cout << "执行了拷贝构造函数" << endl;
}
tempClass &operator=(const tempClass &tobj) {
num1 = tobj.num1;
num2 = tobj.num2;
cout << "执行了拷贝赋值运算符" << endl;
return *this;
}
virtual ~tempClass() {
cout << "执行了析构函数" << endl;
}
public:
int num1;
int num2;
int addFunc(tempClass &tobj);
};
//int tempClass::addFunc(tempClass tobj) 产生了临时变量,会调用拷贝构造函数,return之后会调用析构函数
// int tempClass::addFunc(tempClass tobj) {
// int tmp = tobj.num1 + tobj.num2;
// tobj.num1 = 100;
// return tmp;
// }
//通过引用的方式传值 避免产生临时对象
int tempClass::addFunc(tempClass &tobj) {
int tmp = tobj.num1 + tobj.num2;
tobj.num1 = 100;
return tmp;
}
tempClass::tempClass(int tempnum1,int tempnum2):num1(tempnum1),num2(tempnum2)
{
cout << "执行了构造函数" << endl;
}
tempClass Double(tempClass &tobj) {
tempClass tmp; //会调用构造函数
tmp.num1 = tobj.num1 * 2;
tmp.num2 = tobj.num2 * 2;
return tmp;//调用了析构函数,释放tmp,产生看不见的临时变量调用拷贝构造函数和看不见的临时变量的析构函数
}
// tempClass Double(tempClass &tobj) {
// return tempClass(tobj.num1 * 2,tobj.num2 * 2);//只用了构造函数跟析构函数
// }
1.以传值的方式给函数传递参数
int main()
{
tempClass temp(10,20);
int sum = temp.addFunc(temp);
cout << "sum = " << sum << endl;
cout << "temp.num1 = " << temp.num1 << endl;
return 0;
}
在main中如果addFunc为
- int addFunc(tempClass tobj);执行temp.addFunc(temp);
tempClass tobj会产生临时变量,return之后会会调用析构函数。 - int addFunc(tempClass &tobj);通过引用的方式则不会产生临时不会调用构造函数跟析构函数。
int main()
{
tempClass tm;
tm = 100;//产生了临时对象
//1.用100创建了一个临时对象,调用了构造函数
//2.调用了拷贝赋值运算符
//3.销毁时候调用了析构函数
//改为:
tempClass tmp1 = 100;
//不会产生临时变量,少了上面三个步骤
return 0;
}
2.类型转换生成的临时对象/隐式类型转换以保证函数调用成功
int calc(const string &tempstr,char ch) {
return 1;
}
int main()
{
char mystr[100] = "I Love China!";
int result = calc(mystr,'o'); //char[]转string的转换,calc必须加const
//c++只会给const引用产生临时变量,不会给非const引用产生临时变量
// 想不产生临时变量之间调用string
int result1 = calc("I Love China!",'o');
return 0;
}
- char[]转string的转换,calc必须加const。
- c++只会给const引用产生临时变量,不会给非const引用产生临时变量。
- 想不产生临时变量之间调用string。
3.函数返回对象的时候
int main()
{
tempClass tm1(10,100);
Double(tm1); //因为返回了对象,导致调用拷贝构造函数跟析构函数
//临时对象被tm2或者tm3接管了,只调用拷贝构造函数
tempClass &&tm2 = Double(tm1);
//tempClass tm3 = Double(tm1);
return 0;
}
如果Double改为return tempClass(tobj.num1 * 2,tobj.num2 * 2);//只用了构造函数跟析构函数效率提升。
三、类外运算符重载
class testClass
{
public:
int num1;
int num2;
public:
testClass(int num11 = 0, int num21 = 0) : num1(num11), num2(num21) {}
};
mynum operator+(testClass &tmpnum1, testClass &tmpnum2)
{
return testClass(tmpnum1.num1 + tmpnum2.num1, tmpnum1.num2 + tmpnum2.num2);
}
int main() {
testClass tmp1;
tmp1.num1 = 10;
tmp1.num2 = 100;
testClass tmp2;
tmp2.num1 = 20;
tmp2.num2 = 200;
testClass tmp3 = tmp + tmp2;
}