首先不要使用VC编译器来测试,看看这段代码并猜想它会调用几次构造函数和析构函数,最后再测试一下:
在VC编译运行后结果大失所望吧?不明白不要紧,VC这个集成的IDE开发工具它的“博大精深”值得我们慢慢学习与积累,先看看下面我查找的资料吧:
一、拷贝构造函数
拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的参数(对象的引用)是不可变的(const类型)。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。
在C++中,下面三种对象需要调用拷贝构造函数:
1) 一个对象以值传递的方式传入函数体;
2) 一个对象以值传递的方式从函数返回;
3) 一个对象需要通过另外一个对象进行初始化;
如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是构造函数调用的原因。事实上, 拷贝构造函数是由普通构造函数和赋值操作符共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。
拷贝构造函数不可以改变它所引用的对象,其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。
如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会自动生成一个来进行对象之间的位拷贝(Bitwise Copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数,除非另外一个构造函数在类初始化或构造列表的时候被调用。
拷贝构造函数使程序更有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统会自动为你生成默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。
在C++中,下面三种对象需要调用拷贝构造函数:
1) 一个对象以值传递的方式传入函数体;
2) 一个对象以值传递的方式从函数返回;
3) 一个对象需要通过另外一个对象进行初始化;
如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是构造函数调用的原因。事实上, 拷贝构造函数是由普通构造函数和赋值操作符共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。
拷贝构造函数不可以改变它所引用的对象,其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。
如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会自动生成一个来进行对象之间的位拷贝(Bitwise Copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数,除非另外一个构造函数在类初始化或构造列表的时候被调用。
拷贝构造函数使程序更有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统会自动为你生成默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。
上述开篇的那段代码,因为它并不只是唯一的一个构造函数(实际上调用了四次拷贝构造函数),所以你可以显式的声明一个拷贝构造函数再编译试试,代码如下:
二、程序运行效果:
三、参考资料: