临时对象的产生
直接调用构造函数将产生一个临时对象
临时对象的声明周期只有一条语句的时间
临时对象的作用域只在一条语句中
临时对象是C++中应当警惕的灰色地带
- #include
-
- using namespace std;
-
- class Test
- {
- private:
- int mi;
- public:
- //有参构造函数
- Test(int i)
- {
- mi = i;
- }
-
- //无参构造函数
- Test()
- {
- Test(5); //调用有参构造函数
- }
-
- void print()
- {
- cout << "mi = " << mi << endl;
- }
- };
-
-
- int main()
- {
- Test t; //定义一个类对象,使用无参构造函数
-
- t.print();
-
- return 0;
- }
输出结果
mi = 0
结果分析:
上面的代码,可以看出作者的意图是使用无参的构造函数调用有参构造函数,把对象的成员变量mi初始化为5,但是实际结果却是0(不同的编译器结果是不一样的,应该是随机值)。
代码
- Test()
- {
- Test(5); //调用有参构造函数
- }
在执行Test(5)的时候就得到一个临时对象,因为我们知道,只要构造函数执行完,对象就创建好了,所以执行了Test(5),就有一个对象被创建,这个对象连名字都没有,Test(5)执行完之后这个对象就会被析构,所以上面的构造函数代码等同于,没有调用Test(5).
- Test()
- {
- //Test(5); //调用有参构造函数
- }
是不是很像某人在群里发一个红包,马上自己就抢走了,这个红包的声明周期就在那一瞬间,跟没发红包是一样的。
要避免出现临时对象,就不要调用构造函数;但是又想偷懒,少些点代码,可以编写一个私有的成员函数,然后构造函数调用私有成员函数就可以了。
- #include
-
- using namespace std;
-
- class Test
- {
- private:
- int mi;
-
- //定义一个私有的成员函数
- void init(int i)
- {
- mi =i;
- }
- public:
- //有参构造函数
- Test(int i)
- {
- init(i); //构造函数调用私有成员函数
- }
-
- //无参构造函数
- Test()
- {
- init(5); //构造函数调用私有成员函数
- }
-
- void print()
- {
- cout << "mi = " << mi << endl;
- }
- };
-
-
- int main()
- {
- Test t; //定义一个类对象,使用无参构造函数
-
- t.print();
-
- return 0;
- }
输出结果:
mi = 5
这样目的就达到了。
在构造函数中调用构造函数的情况有点特殊,在main函数调用构造函数也会产生临时对象,如下面代码所示
- #include
-
- using namespace std;
-
- class Test
- {
- private:
- int mi;
-
- public:
- //有参构造函数
- Test(int i)
- {
- mi = i;
- cout << "using Test(int i).\n";
- }
-
- //无参构造函数
- Test()
- {
- cout << "using Test().\n";
- }
-
- //析构函数
- ~Test()
- {
- cout << "using ~Test().\n";
- }
-
-
- void print()
- {
- cout << "mi = " << mi << endl;
- }
- };
-
-
- int main()
- {
- cout << "main begin.\n";
- Test(); //只要调用了构造函数就会创建一个对象,这句执行完就析构了
-
- Test(5);//只要调用了构造函数就会创建一个对象,这句执行完就析构了
-
- cout << "main end.\n";
-
-
- return 0;
- }
输出结果
- main begin.
- using Test().
- using ~Test().
- using Test(int i).
- using ~Test().
- main end.
可以看出,在main函数中调用构造函数,执行完构造函数之后马上就调用析构函数。
C++的临时对象跟C语言的野指针有的一拼,能避免就避免。