一:临时对象的概念
i++,++i
int i = 1;
int&& r1 = i++; //r1和i之间没有什么关系
r1 = 19;
i = 80;
另外一些临时对象,是因为我们代码书写问题而产生的。统一称临时变量为临时对象。new /delete、栈。
二:产生临时对象的情况和解决,三种情况和解决方案
<1>以传值的方式给函数传递参数 CTempValue
class CTempValue
{
public:
int val1;
int val2;
public:
CTempValue(int v1 = 0, int v2 = 0); //构造函数
CTempValue(const CTempValue& v) : val1(v.val1), val2(v.val2)
{
cout << "调用了拷贝构造函数" << endl;
}
CTempValue& operator=(const CTempValue& tempv)
{
cout << "调用了拷贝赋值运算符" << endl;
cout << "tempv.val1: " << tempv.val1 << endl;
cout << "tempv.val2: " << tempv.val2 << endl;
return *this;
}
virtual ~CTempValue()
{
cout << "调用了析构函数" << endl;
}
public:
int Add(CTempValue& tobj);
};
CTempValue::CTempValue(int v1, int v2) : val1(v1), val2(v2)
{
cout << "调用了构造函数" << endl;
cout << "val1 = " << val1 << endl;
cout << "val2 = " << val2 << endl;
}
int CTempValue::Add(CTempValue& tobj)
{
int temp = tobj.val1 + tobj.val2;
tobj.val1 = 1000;
return temp;
}
int main()
{
CTempValue tv(10, 20); //调用构造函数
cout << "***********************" << endl;
int sum = tv.Add(tv); //这个会导致拷贝构造函数的执行
cout << "***********************" << endl;
cout << "sum = " << sum << endl;
cout << "tv.val1 = " << tv.val1 << endl;
cin.get();
return 0;
}
<2>类型转换生成临时对象 / 隐式类型转换以保证函数调用成功
CTempValue sum;
sum = 1000; //这里产生了一个真正的临时对象
1>用1000这个数字创建了一个类型为CTempValue的临时对象
2>调用拷贝赋值运算符把这个临时对象里面的各个成员值赋值给了sum对象,
3>销毁这个临时创建的CTempValue
CTempValue sum = 1000; //把定义对象和给对象初值放在一行上。这个等号不是赋值运算符了,是定义时初始化。为sum对象预留了空间,用1000构造 sum 对象,而且是直接构造在 sum 对象的预留空间里。
隐式类型转换以保证函数调用成功
char mystr[100] = “I love China, oh, yeah!”;
string mystr2 = “I love China, oh, yeah!”;
int result = calc(mystr, ‘o’); //char[], string
C++语言只会为const引用 (const string& strsource) 产生临时变量,而不会为非 const 引用 (string& strsource) 这种参数产生临时变量。
int calc(const string& strsource)
{
cout << "int calc(const string& strsource)" << endl;
const char* p = strsource.c_str();
cout << "p: " << p << endl;
int icount = 0;
return icount;
}
int calc(string& strsource)
{
cout << "int calc(string& strsource)" << endl;
const char* p = strsource.c_str();
cout << "p: " << p << endl;
int icount = 0;
return icount;
}
int main()
{
CTempValue sum;
sum = 1000;
CTempValue sum = 1000;
{
char mystr[100] = "i love china";
int result = calc(mystr); //调用的是第一个
}
cout << "***********************" << endl;
{
string mystr = "i love china";
int result = calc(mystr); //调用的是第二个
}
cout << "***********************" << endl;
{
const string mystr = "i love china";
int result = calc(mystr); //调用的是第一个
}
cout << "***********************" << endl;
}
<3>函数返回对象的时候
CTempValue ts1(10, 20);
Double(ts1); //因为返回临时对象导致占用了一个拷贝构造函数和一个析构函数
第一个析构函数是tmp的,第二个析构函数是 系统构造要返回的临时对象的
CTempValue ts3 = Double(ts1);
CTempValue&& ts4 = Double(ts1); //临时对象是一种右值 临时对象被ts4接管了
Double()函数引起的消耗
CTempValue tmpm:会消耗一个构造函数和一个析构函数。
return tmp:产生临时对象,占用一个拷贝构造函数和析构函数。
在举一例:介绍知识点,类外运算符重载。
Time &Time::operator=(cosnt Time &tmpTime){… return *this;}
CTempValue Double(CTempValue& ts)
{
//CTempValue tempm;
//tempm.val1 = ts.val1 * 2;
//tempm.val2 = ts.val2 * 2;
//return tempm;
return CTempValue(ts.val1 * 2, ts.val2 * 2);
}
CTempValue ts1(10, 20);
cout << "***********************" << endl;
//CTempValue ts3 = Double(ts1);
CTempValue&& ts4 = Double(ts1);
临时对象就是一种右值。
<4>类外的运算符重载之中的优化
class mynum
{
public:
mynum()
{
cout << "调用了构造函数" << endl;
}
mynum(const mynum& t)
{
cout << "调用了拷贝构造函数" << endl;
}
virtual ~mynum()
{
cout << "调用了析构函数" << endl;
}
public:
int num1;
int num2;
};
mynum operator+(mynum& tmpnum1, mynum& tmpnum2)
{
mynum result;
result.num1 = tmpnum1.num1 + tmpnum2.num1;
result.num2 = tmpnum1.num2 + tmpnum2.num2;
return result;
}
int main()
{
mynum tm1;
tm1.num1 = 10;
tm1.num2 = 100;
mynum tm2;
tm2.num1 = 20;
tm2.num2 = 200;
mynum tm3 = tm1 + tm2;
}
优化后,少调用了一次拷贝构造函数,也少调用了一次析构函数。
class mynum
{
public:
mynum(const mynum& t)
{
cout << "调用了拷贝构造函数" << endl;
}
mynum(int x = 0, int y = 0) : num1(x), num2(y)
{
cout << "调用了构造函数" << endl;
}
virtual ~mynum()
{
cout << "调用了析构函数" << endl;
}
public:
int num1;
int num2;
};
mynum operator+(mynum& tmpnum1, mynum& tmpnum2)
{
return mynum(tmpnum1.num1 + tmpnum2.num1, tmpnum1.num2 + tmpnum2.num2);
}
int main()
{
mynum tm1;
tm1.num1 = 10;
tm1.num2 = 100;
mynum tm2;
tm2.num1 = 20;
tm2.num2 = 200;
mynum tm3 = tm1 + tm2;
}