84669 Lernen von Personen
152542 Lernen von Personen
20005 Lernen von Personen
5487 Lernen von Personen
7821 Lernen von Personen
359900 Lernen von Personen
3350 Lernen von Personen
180660 Lernen von Personen
48569 Lernen von Personen
18603 Lernen von Personen
40936 Lernen von Personen
1549 Lernen von Personen
1183 Lernen von Personen
32909 Lernen von Personen
学习是最好的投资!
原因在于优化.先来分析你的程序, a1是一个实例, a2是一个, getTest传参是传值那么会有一个Temp1, getTest又有一个return Temp2. 所以一共应该是四个对象.
但是, 编译器会有优化, 甚至在你禁止优化的时候也会有一点点优化. 比如getTest的返回值, 本来按照语义是需要调用operator=, 实际上编译器通常是直接调用CTest1(const CTest1&)这个构造函数, 把两次构造优化成1次.
operator=
CTest1(const CTest1&)
你那个代码, 把析构函数里面的cout注释掉, 就会发现只构造了3次. 因为析构函数里面什么都没有的话, 编译器开启那个优化, 对你的代码功能上就没有任何影响. 但是你开cout的话, 一旦优化掉的话, 代码的功能可能就不正确了.
你删掉析构函数里面的cout, 用gcc编译, 添加参数-O0 -fno-elide-constructors, 实际上还是四个对象.
-O0 -fno-elide-constructors
CTest1 getTestObj(CTest1 obj) { return obj; /* copy */ } int main() { CTest1 a1; // construct CTest1 a2 = /* copy */ getTestObj(a1/* copy */); return 0; }
关于返回值有一种对编译器来说省事的方式,叫做返回值优化(RVO - return value optimization)。编译器会省略一步对象的COPY构造调用,不知道LZ用的什么编译器,在gcc(4.8.3)上面是默认开启的,就是说结果是这样的:
Constructor of CTest1:0 Copy constructor of CTest1:1 Copy constructor of CTest1:2 //如果去掉注释 就会打印下面三句话 destroy id:1 destroy id:2 destroy id:0
原因在于优化.
先来分析你的程序, a1是一个实例, a2是一个, getTest传参是传值那么会有一个Temp1, getTest又有一个return Temp2. 所以一共应该是四个对象.
但是, 编译器会有优化, 甚至在你禁止优化的时候也会有一点点优化. 比如getTest的返回值, 本来按照语义是需要调用
operator=
, 实际上编译器通常是直接调用CTest1(const CTest1&)
这个构造函数, 把两次构造优化成1次.你那个代码, 把析构函数里面的cout注释掉, 就会发现只构造了3次. 因为析构函数里面什么都没有的话, 编译器开启那个优化, 对你的代码功能上就没有任何影响. 但是你开cout的话, 一旦优化掉的话, 代码的功能可能就不正确了.
你删掉析构函数里面的cout, 用gcc编译, 添加参数
-O0 -fno-elide-constructors
, 实际上还是四个对象.关于返回值有一种对编译器来说省事的方式,叫做返回值优化(RVO - return value optimization)。编译器会省略一步对象的COPY构造调用,不知道LZ用的什么编译器,在gcc(4.8.3)上面是默认开启的,就是说结果是这样的: