3-13 临时对象深入探讨、 类外运算符重载

一、临时对象的概念

    // 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;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值