C++中真正的临时对象是不可见的,在源代码中不会出现,且不在堆上分配内存(在栈中),没有名字的对象;
//i++ ++i
//i++ 会产生一个临时对象,用来记录i的值;
int i = 1;
int &&r = i++; //i和r没关系
临时对象可能发生于如下的三种情况,我们需要了解这些临时对象如何被产生和被销毁;以及如何避免产生临时对象,避免不必要的调用构造和析构;进一步提升程序的性能;
#include <iostream>
using namespace std;
class CTempValue
{
public:
int m_val;
int m_v;
public:
CTempValue(int i = 0, int j = 0);
CTempValue(const CTempValue& t) :m_val(t.m_val), m_v(t.m_v)
{
cout << "执行拷贝构造函数" << endl;
}
virtual ~CTempValue()
{
cout << "执行析构函数" << endl;
}
int add(CTempValue tmp); //普通函数
};
CTempValue::CTempValue(int i, int j):m_val(i), m_v(j)
{
cout << "执行构造函数" << endl;
cout << "m_val = " << m_val << endl;
cout << "m_v = " << m_v << endl;
}
int CTempValue::add(CTempValue tmp)
{
int tmp_val = tmp.m_val + tmp.m_v;
tmp.m_val = 1000;
return tmp_val;
}
int main()
{
CTempValue tmp(10, 20); //构造函数执行
int Sum = tmp.add(tmp); //拷贝构造函数和析构函数会执行
//add的形式参数会拷贝实参 使用拷贝构造函数
//形参的释放 调用析构函数
cout << "Sum = " << Sum << endl;
cout << "tmp.m_val = " << tmp.m_val << endl;
}
通过引用传参解决
#include <iostream>
using namespace std;
class CTempValue
{
public:
int m_val;
int m_v;
public:
CTempValue(int i = 0, int j = 0);
CTempValue(const CTempValue& t) :m_val(t.m_val), m_v(t.m_v)
{
cout << "执行拷贝构造函数" << endl;
}
virtual ~CTempValue()
{
cout << "执行析构函数" << endl;
}
int add(CTempValue& tmp); //普通函数
};
CTempValue::CTempValue(int i, int j):m_val(i), m_v(j)
{
cout << "执行构造函数" << endl;
cout << "m_val = " << m_val << endl;
cout << "m_v = " << m_v << endl;
}
int CTempValue::add(CTempValue& tmp)
{
int tmp_val = tmp.m_val + tmp.m_v;
tmp.m_val = 1000;
return tmp_val;
}
int main()
{
CTempValue tmp(10, 20); //构造函数执行
int Sum = tmp.add(tmp); //拷贝构造函数和析构函数不会执行
cout << "Sum = " << Sum << endl;
cout << "tmp.m_val = " << tmp.m_val << endl;
}
示例1
将一个整型值赋值给一个CTempValue对象,会发生隐式类型转换;
#include <iostream>
using namespace std;
class CTempValue
{
public:
int m_val;
int m_v;
public:
CTempValue(int i = 0, int j = 0);
CTempValue(const CTempValue& t) :m_val(t.m_val), m_v(t.m_v)
{
cout << "执行拷贝构造函数" << endl;
}
//拷贝赋值运算符
CTempValue& operator=(const CTempValue& tmp)
{
m_val = tmp.m_val;
m_v = tmp.m_v;
cout << "执行拷贝赋值运算符" << endl;
return *this;
}
virtual ~CTempValue()
{
cout << "执行析构函数" << endl;
}
int add(CTempValue& tmp); //普通函数
};
CTempValue::CTempValue(int i, int j):m_val(i), m_v(j)
{
cout << "执行构造函数" << endl;
cout << "m_val = " << m_val << endl;
cout << "m_v = " << m_v << endl;
}
int CTempValue::add(CTempValue& tmp)
{
int tmp_val = tmp.m_val + tmp.m_v;
tmp.m_val = 1000;
return tmp_val;
}
int main()
{
CTempValue sum;
sum = 1000; //会产生一个临时对象; 调用一次构造函数一次析构函数
}
解决方法
通过定义时初始化对象来达到不生成临时对象的目的;
=是定义时初始化;系统为对象预留空间 用1000构造对象,而且是直接构造在对象预留空间中;
#include <iostream>
using namespace std;
class CTempValue
{
public:
int m_val;
int m_v;
public:
CTempValue(int i = 0, int j = 0);
CTempValue(const CTempValue& t) :m_val(t.m_val), m_v(t.m_v)
{
cout << "执行拷贝构造函数" << endl;
}
//拷贝赋值运算符
CTempValue& operator=(const CTempValue& tmp)
{
m_val = tmp.m_val;
m_v = tmp.m_v;
cout << "执行拷贝赋值运算符" << endl;
return *this;
}
virtual ~CTempValue()
{
cout << "执行析构函数" << endl;
}
int add(CTempValue& tmp); //普通函数
};
CTempValue::CTempValue(int i, int j):m_val(i), m_v(j)
{
cout << "执行构造函数" << endl;
cout << "m_val = " << m_val << endl;
cout << "m_v = " << m_v << endl;
}
int CTempValue::add(CTempValue& tmp)
{
int tmp_val = tmp.m_val + tmp.m_v;
tmp.m_val = 1000;
return tmp_val;
}
int main()
{
/*
CTempValue sum;
sum = 1000;
*/ //会产生一个临时对象; 调用一次构造函数一次析构函数 一次拷贝赋值运算符
//1. 用1000创建CTempValue的临时对象
//2. 调用拷贝赋值运算符把这个临时对象里面的各个成员赋值给sum对象
//3. 销毁这个临时创建的CTempValue对象
CTempValue sum = 1000; //没有生成临时对象 =是定义时初始化;系统为sum预留空间 用1000构造sum对象,而且是直接构造在sum对象预留空间中;
}
示例2
//统计字符ch在str中出现的次数
int total(const string &str, char ch) //将str绑定到string临时对象上 去掉const报错 系统不允许修改临时对象
{
const char* p = str.c_str();
int count = 0;
return count;
}
int main()
{
char mystr[100] = "hello world";
int res = total(mystr, ‘o‘); //隐式类型转化 会产生临时对象string
//c++只会为const引用产生临时对象,而不会为非const引用产生临时对象???
}
优化
当函数需要返回一个对象,它会在栈中创建一个临时对象,存储函数的返回值。
范例1
#include <iostream>
using namespace std;
class CTempValue
{
public:
int m_val;
int m_v;
public:
CTempValue(int i = 0, int j = 0);
CTempValue(const CTempValue& t) :m_val(t.m_val), m_v(t.m_v)
{
cout << "执行拷贝构造函数" << endl;
}
//拷贝赋值运算符
CTempValue& operator=(const CTempValue& tmp)
{
m_val = tmp.m_val;
m_v = tmp.m_v;
cout << "执行拷贝赋值运算符" << endl;
return *this;
}
virtual ~CTempValue()
{
cout << "执行析构函数" << endl;
}
int add(CTempValue& tmp); //普通函数
};
CTempValue::CTempValue(int i, int j):m_val(i), m_v(j)
{
cout << "执行构造函数" << endl;
cout << "m_val = " << m_val << endl;
cout << "m_v = " << m_v << endl;
}
int CTempValue::add(CTempValue& tmp)
{
int tmp_val = tmp.m_val + tmp.m_v;
tmp.m_val = 1000;
return tmp_val;
}
CTempValue Double(CTempValue& tmp)
{
CTempValue tmp_value; //构造 + 析构
tmp_value.m_v = tmp.m_v * 2;
tmp_value.m_val = tmp.m_val * 2;
return tmp_value; //产生临时对象 调用拷贝构造函数和析构函数
}
int main()
{
CTempValue x(10, 20); //构造 + 析构
//Double(x);
CTempValue&& y = Double(x); //临时对象是一种右值
CTempValue z = Double(x);
}
优化
#include <iostream>
using namespace std;
class CTempValue
{
public:
int m_val;
int m_v;
public:
CTempValue(int i = 0, int j = 0);
CTempValue(const CTempValue& t) :m_val(t.m_val), m_v(t.m_v)
{
cout << "执行拷贝构造函数" << endl;
}
//拷贝赋值运算符
CTempValue& operator=(const CTempValue& tmp)
{
m_val = tmp.m_val;
m_v = tmp.m_v;
cout << "执行拷贝赋值运算符" << endl;
return *this;
}
virtual ~CTempValue()
{
cout << "执行析构函数" << endl;
}
int add(CTempValue& tmp); //普通函数
};
CTempValue::CTempValue(int i, int j):m_val(i), m_v(j)
{
cout << "执行构造函数" << endl;
cout << "m_val = " << m_val << endl;
cout << "m_v = " << m_v << endl;
}
int CTempValue::add(CTempValue& tmp)
{
int tmp_val = tmp.m_val + tmp.m_v;
tmp.m_val = 1000;
return tmp_val;
}
CTempValue Double(CTempValue& tmp)
{
return CTempValue(tmp.m_val * 2, tmp.m_v * 2);
}
int main()
{
CTempValue x(10, 20); //构造 + 析构
//Double(x);
CTempValue&& y = Double(x); //临时对象是一种右值
//CTempValue z = Double(x);
}
范例2:类外运算符重载
class mynum
{
public:
int x;
int y;
};
mynum operator+(mynum& num1, mynum& num2)
{
mynum res;
res.x = num1.x + num2.x;
res.y = num1.y + num2.y;
return res;
}
int main()
{
mynum num1;
num1.x = 1;
num1.y = 2;
mynum num2;
num2.x = 3;
num2.y = 4;
mynum num3 = num1 + num2;
}
优化
class mynum
{
public:
int x;
int y;
public:
mynum(int x = 0, int y = 0) :x(x), y(y) {};
};
mynum operator+(mynum& num1, mynum& num2)
{
return mynum(num1.x + num2.x, num1.y + num2.y);
}
int main()
{
mynum num1;
num1.x = 1;
num1.y = 2;
mynum num2;
num2.x = 3;
num2.y = 4;
mynum num3 = num1 + num2;
}
参考:《More Effective C++》条款19(p98)
原文:https://www.cnblogs.com/Trevo/p/13343866.html