一、临时对象的概念
// i++,++i
int i = 1;
int &&r1 = i++; // 右值引用 r1和i之间没有什么关系
r1 = 19;
i = 80;
另外一些临时对象,是因为我们代码书写问题而产生的,统一称临时变量为临时对象
new(堆) delete(释放new的对象) 栈(临时对象)
二、产生临时对象的情况和解决:三种情况和解决方案
1.以传值的方式给函数传递参数:
class CTempValue
{
public:
int val1;
int val2;
public:
CTempValue(int v1 = 0, int v2 = 0);
CTempValue(const CTempValue &t) :val1(t.val1), val2(t.val2) // 拷贝构造函数
{
cout << "copy construct" << endl;
}
virtual ~CTempValue() // 析构函数
{
cout << "destructor" << endl;
}
CTempValue& operator=(const CTempValue &tmp) // 拷贝复制运算符
{
val1 = tmp.val1;
val2 = tmp.val2;
cout << "Copy replication operator " << endl;
return *this;
}
public:
int Add(CTempValue tObj); // 普通函数
int Add1(CTempValue &tObj);
};
int CTempValue::Add(CTempValue tObj) // 拷贝构造函数在tObj这个临时对象发生
{
int tmp = tObj.val1 + tObj.val2;
tObj.val1 = 1000; // 对外界的之没有影响
return tmp; // 会调用析构函数
}
// main函数调用
CTempValue tm(10, 20); // 调用了构造函数
int Sum = tm.Add(tm); // 调用了拷贝构造函数
cout << "Sum = " << Sum << endl;
cout << "tm.val1 = " << tm.val1 << endl;
改进后:改成引用(就会少一次拷贝构造)
int CTempValue::Add1(CTempValue &tObj)
{
int tmp = tObj.val1 + tObj.val2;
tObj.val1 = 1000; // 会修改val1的值
return tmp;
}
// main函数调用
CTempValue tm(10, 20); // 调用了构造函数
int Sum = tm.Add(tm);
cout << "Sum = " << Sum << endl;
cout << "tm.val1 = " << tm.val1 << endl;
2.类型转换生成的临时对象 / 隐式类型转换以保证函数调用成功
class TmpValue{
public:
int val1;
int val2;
public:
TmpValue(int v1=0, int v2=0);
TmpValue(const TmpValue &tmp);
int Add(TmpValue tpobj);
virtual ~TmpValue();
TmpValue & operator=(const TmpValue &tmp);
};
TmpValue::TmpValue(int v1=0, int v2=0):val1(v1), val2(v2)
{
}
TmpValue::TmpValue(const TmpValue &tmp):val1(tmp.val1), val2(tmp.val2)
{
cout << "调用了拷贝构造函数" << endl;
}
TmpValue::~TmpValue()
{
cout << "调用了析构函数" << endl;
}
int TmpValue::Add(TmpValue tpobj) //tpobj不属于真正的临时对象,真正的临时对象是
//临时生成且在代码中不可见的
{
int Sum = tpobj.val1 + tpobj.val2;
tpobj.val1 = 100;
return Sum;
}
TmpValue & TmpValue::operator=(const TmpValue &tmp)
{
val1 = tmp.val1;
val2 = tmp.val2;
return *this;
}
int main()
{
TmpValue tp2;
tp2 = 1000; //这里发生了隐式转换,产生了临时对象,调用了CTempValue的
//TmpValue(int v1, int v2)构造函数
//tp2.val1的值赋值为100
}
加了赋值运算符重载之后
(1) :用1000这个函数创建一个类型为cTest的临时对象
(2):调用拷贝赋值运算符函数,把值传送给ct对象
(3):销毁这个临时创建的cTest对象
改进:
// 把定义对象和给对象初值放在一行上
// 用1000构造sumx对象,而且是直接构造在sumx对象预留空间里
TempValue sumx = 1000; // 只调用了一次构造函数
隐式类型转换以保证函数调用成功
#include <iostream>
using namespace std;
// 统计字符ch在字符串strsource里出现的次数,把次数返回回去
int calcCount(const string &strsource, char ch)// strsource这个形参绑定到了string这个临时对象
{// 若不加const 则认为会修改strsource这个临时对象
const char *p = strsource.c_str();
int icount = 0;
// ......
return icount;
}
// main函数调用
char mystr[100] = "I love china!oh yeah!";
int result = calcCount(mystr,'o'); // char[] --> string 会产生临时对象
//C++语言只会为const引用(const string &strsource)产生临时变量,而不会为非const引用产生临时变量
string mystr1 = "I love china!oh yeah!";
result = calcCount(mystr, 'o'); // 这样加const与不加const时一样的,因为不需要产生临时对象
3.函数返回对象的时候
#include <iostream>
using namespace std;
class cTempValue{
public:
cTempValue(int a = 0, int b = 0)
{
val1 = a; val2 = b;
cout << "调用了构造函数" << endl;
cout << val1 << "和" << val2 << endl;
}
cTempValue(const cTempValue & tm){
cout << "拷贝构造" << endl;
}
virtual ~cTempValue()
{
cout << "析构" << endl;
}
public:
int val1;
int val2;
};
cTempValue Double(cTempValue &ts ) {
cTempValue temp; //这个会消耗一个构造和析构的调用
temp.val1 = ts.val1 * 2;
temp.val2 = ts.val2 * 2;
return temp;//产生临时对象,会有拷贝构造和析构
}
int main()
{
cTempValue test(10,20);
Double(test); //因为返回临时对象,占用一个拷贝构造函数和析构
system("pause");
}
这里的构造函数是temp返回的时候产生一个临时对象,第一次析构是因为temp的析构。第二次的析构是临时对象的。
因为这里呗test3来承接了。所以没有被立即析构。
这里同理。临时对象是一种右值。
改进:
、、
类外运算符重载:
class mynum
{
public:
int num1;
int num2;
public:
mynum(int num11 = 0, int num21 = 0) : num1(num11), num2(num21) {}
};
mynum operator+(mynum &tmpnum1, mynum &tmpnum2)
{
return mynum(tmpnum1.num1 + tmpnum2.num1, tmpnum1.num2 + tmpnum2.num2);
}
// main函数调用
mynum tmp;
tmp.num1 = 10;
tmp.num2 = 100;
mynum tmp2;
tmp2.num1 = 20;
tmp2.num2 = 200;
mynum tmp3 = tmp + tmp2;