C++拷贝构造函数与赋值构造函数
本章主要记录一下C/C++基础方面的一些内容,以备后续查验。当前所使用编译器版本:
# gcc --version gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44) Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1. 前言
C++中经常用到拷贝构造函数、赋值构造函数,这些函数的调用时机各有区别,这里进行简单总结:
先写一个类,用作之后的示例:
2. 拷贝构造函数
1) 对象需要通过另外一个对象进行初始化
编译运行:
# gcc -o test test.cpp -lstdc++ -std=c++11 # ./test address: 0x8a722030 point: 0x10c2010 value: 1 拷贝构造 global address: 0x8a722020 point: 0x10c2010 value: 1 delete: 0x8a722020 delete: 0x8a722030
2) 对象通过值传递方式进入函数
编译运行:
# gcc -o test test.cpp -lstdc++ -std=c++11 # ./test address: 0x62020930 point: 0x1694010 value: 1 拷贝构造 stack address: 0x62020940 point: 0x1694010 value: 1 delete: 0x62020940 delete: 0x62020930
3) 当对象以值传递的方式从函数返回
编译时发生错误,提示”return ret”调用了被禁止使用的拷贝构造函数:
error: use of deleted function 'A:A(const A&)'
若将拷贝构造函数
放开,则能正常编译:
# gcc -o test test.cpp -lstdc++ -std=c++11 # ./test address: 0xd34cdc60 point: 0x1b1c010 value: 3 stack address: 0xd34cdc60 point: 0x1b1c010 value: 3 global address: 0xd34cdc60 point: 0x1b1c010 value: 3 delete: 0xd34cdc60
关于此种情况还有如下:
编译运行:
# gcc -o test test.cpp -lstdc++ -std=c++11 # ./test address: 0x81dcdff0 point: 0x874010 value: 20 global address: 0x81dcdff0 point: 0x874010 value: 20 delete: 0x81dcdff0
3. 赋值构造函数
1) 对象以值传递方式从函数返回,且接受返回值的对象已经初始化过
编译运行:
# gcc -o test test.cpp -lstdc++ -std=c++11 [root@compile just_for_test]# ./test address: 0xfa9d51c0 point: 0x1ab3010 value: 3 stack address: 0xfa9d51c0 point: 0x1ab3010 value: 3 赋值构造 delete: 0xfa9d51c0 global address: 0xfa9d51b0 point: 0x1ab3010 value: 3 delete: 0xfa9d51b0
2) 对象直接赋值给另一个对象,且接受值的对象已经初始化过
编译运行:
# gcc -o test test.cpp -lstdc++ -std=c++11 # ./test address: 0xc36068d0 point: 0x2183010 value: 1 赋值构造 global address: c36068c0, point: 2183010, value: 1 delete: 0xc36068c0 delete: 0xc36068d0
注: 如果把上面的赋值构造函数
注释掉,还是会调用默认的赋值构造函数。
4. 移动构造函数
编译运行:
# gcc -o test test.cpp -lstdc++ -std=c++11 # ./test address: 0x414b3e90 point: 0x21aa010 value: 200 移动构造 delete: 0x414b3e90 global address: 0x414b3e80 point: 0x21aa010 value: 200 delete: 0x414b3e80
注意: 这里移动构造赋值也只会调用一次构造函数。
5. 总结
对象以值传递方式从函数返回时,若接受返回值的对象已经初始化过,则会调用赋值构造函数,且该对象还会调用析构函数,当对象中包含指针时,会使该指针失效,因此需要重载赋值构造函数,使用类似深拷贝或移动构造函数
的方法赋值,才能避免指针失效。
对象以值传递方式从函数返回时,若接受返回值的对象是由该返回值初始化,则不会调用任何构造函数,且不会调用析构函数。(这一点,请参看上面2.3部分)。
[参看]: