有趣的问题下面的程序输出什么?为什么?class Test{private: int mi;public: Test(int i) { mi = i; } Test() { Test(0); // 注意这里! } void print() { printf(“mi = %d\n”, mi); }};==>int main(){ Test t; t.print(); return 0;}实例分析: 有趣的问题#include <stdio.h>class Test{private: int mi;public: Test(int i) { mi = i; } Test() { Test(0); } void print() { printf(“mi = %d\n”, mi); }};int main(){ Test t; t.print(); return 0;}输出:mi = 11341812发生了什么程序意图 : 【代码复用】在 Test() 中以 0 作为参数调用 Test(int i)将成员变量 mi 的初始值设置为 0运行结果成员变量 mi 的值为随机值究竟哪个地方出了问题?思考构造函数是一个特殊的函数是否可以直接调用?是否可以在构造函数中调用构造函数?直接调用构造函数的行为是什么?答案直接调用构造函数将产生一个临时对象临时对象的生命周期只有一条语句的时间临时对象的作用域只在一条语句中临时对象是C++中值得警惕的灰色地带编程实验: 解决方案定义私有的的可复用普通成员函数#include <stdio.h>class Test{private: int mi; void init(int i) { // do other something … mi = i; }public: Test(int i) { init(i); } Test() { init(0); } void print() { printf(“mi = %d\n”, mi); }};int main(){ Test t; t.print(); return 0;}输出:mi = 0编译器的行为现代 C++ 编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生!!!编程实验: 神秘的临时对象#include <stdio.h>class Test{private: int mi;public: Test(int i) { printf(“Test(int i) : %d\n”, i); mi = i; } Test(const Test& t) { printf(“Test(const Test& t) : %d\n”, t.mi); mi = t.mi; } Test() { printf(“Test()\n”); mi = 0; } void print() { printf(“mi = %d\n”, mi); } ~Test() { printf("Test()\n"); }};Test func(){ return Test(20);}int main(){ Test t = Test(10); // ==> Test t = 10; Test tt = func(); // ==> Test tt = Test(20); ==> Test tt = 20; t.print(); tt.print(); return 0;}输出:【g++】Test(int i) : 10Test(int i) : 20mi = 10mi = 20Test()~Test()分析:1. Test t = Test(10); 为什么拷贝构造函数没有被调用呢?在古老的编译器中,会发生如下过程:a. 生成临时对象(调用构造函数)b. 用临时对象初始化 t (调用拷贝构造函数)2. Test tt = func(); 为什么拷贝构造函数没有被调用呢?在古老的编译器中,会发生如下过程:a. 生成临时对象(调用构造函数)b. 返回临时对象,初始化 tt (调用拷贝构造函数)使用临时对象初始化对象,将额外产生一次拷贝函数的调用,C++ 编译器为了避免性能损失,在不影响最终执行结果的前提下,尽力减少临时对象的产生。Test t = Test(10); ==> Test t = 10;Test tt = func(); ==> Test tt = Test(20); ==> Test tt = 20;小结直接调用构造函数将产生一个临时对象临时对象是性能的瓶颈,也是 bug 的来源之一现代 C++ 编译器会尽力避开临时对象实际工程开发中需要人为的避开临时对象设计时有意识避开编码时有意识避开 Test t = Test(10); ==> Test t = 10;以上内容参考狄泰软件学院系列课程,请大家保护原创!