临时对象是C++ 中的隐藏概念, 在函数参数值传递, 函数返回值, 仿函数上
都会有不同的引用,需要对其有进一步的了解!
先举个小例子:
#include <iostream>
class CTest
{
public:
CTest(int i)
{
m_a = i;
std::cout<<"Enter constructor CTest(int), m_a: "<<m_a<<std::endl;
std::cout<<"this: "<<this<<std::endl;
}
CTest(int i, int j)
{
m_a = i;
m_b = j;
std::cout<<"Enter constructor CTest(int, int), m_a: "
<<m_a<<" m_b: "<<m_b<<std::endl;
std::cout<<"this: "<<this<<std::endl;
}
CTest(const CTest &oCTest)
{
m_a = oCTest.m_a;
m_b = oCTest.m_b;
std::cout<<"Enter copy constructor CTest(const CTest&), m_a: "
<<m_a<<" m_b: "<<m_b<<std::endl;
std::cout<<"&oCTest: "<<&oCTest<<std::endl;
std::cout<<"this: "<<this<<std::endl;
}
protected:
private:
int m_a;
int m_b;
};
void func(CTest oCTest)
{
std::cout<<"Enter func()"<<std::endl;
std::cout<<"&oCTest: "<<&oCTest<<std::endl;
}
int main(int argc, char* argv[])
{
//创建临时对象CTest(1),运行的时候会调用构造函数进行创建
//但是在进入func中,并不会为形参调用拷贝构造函数,因为使用临时对象
//给形参进行拷贝构造是损耗性能的(先构造临时对象-> 对形参进行拷贝
//构造),这个时候编译器实际上是把临时变量的引用直接付给形参的
//(不用害怕形参改变对象内部的数据,实际上你想怎么改都可以,因为
//外部的临时变量生命周期在函数调用退出后就释放了:> 这样的话
//只构造临时对象就可以了,不需要对形参进行拷贝构造)
func(CTest(1));
//为什么做这个测试,主要是阐述一下自己的观点,这几天看了不少介绍临时
//对象的文章,一直都讲得云里雾里讲的不是很清楚,其中多数认为在
//func(CTest oCTest)中编译器自动优化为CTest oCTest = 1;所以没有
//进行拷贝构造。个人认为这种解释是不太合理的,因为CTest oCTest = 1
//这种方式也是需要拷贝构造的,实际上测试结果是没有做拷贝构造,测试一
//下多参数构造情况结果一样,还是不会进行拷贝构造。
//所以我还是倾向于为了优化性能,只复制引用的解释。
func(CTest(2,3));
//下面的是传统的为形参进行拷贝构造的情况。
CTest oCTest1(4);
std::cout<<"&oCTest1: "<<&oCTest1<<std::endl;
func(oCTest1);
return 0;
}
===================
输出:
Enter constructor CTest(int), m_a: 1
this: 003CFC28
Enter func()
&oCTest: 003CFC28
Enter constructor CTest(int, int), m_a: 2 m_b: 3
this: 003CFC28
Enter func()
&oCTest: 003CFC28
Enter constructor CTest(int), m_a: 4
this: 003CFD24
&oCTest1: 003CFD24
Enter copy constructor CTest(const CTest&), m_a: 4 m_b: -858993460
&oCTest: 003CFD24
this: 003CFC28
Enter func()
&oCTest: 003CFC28
注意:
可能有人发现三个临时对象的地址相同, 那是因为头一个临时对象释放后, 下个临时对象会申请到它的的空间, 但是临时对象的内部数据是不同的哦!