共计 1754 个字符,预计需要花费 5 分钟才能阅读完成。
有趣的问题
下面的程序输出什么?为什么?
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) : 10
Test(int i) : 20
mi = 10
mi = 20
~Test()
~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;
以上内容参考狄泰软件学院系列课程,请大家保护原创!