积极答复者
c++拷贝构造函数的疑惑

问题
答案
-
问题一:
大家都知道只有在创建某个类的实例时,才会自动的调用构造。 第一种写法 MyClass B = A; 在声明了一个MyClass 类型的实例B的同时,同时给B赋值。因此会调用到MyClass 的拷贝构造。 第二种写法: MyClass A,B; // 这一行执行完,B对象就创建成功了,也就是说, 这行代码执行完成后, 系统已经为B调用完成了合适的构造。 B = A; 此时只能去寻找MyClass 是否有合适的运算符重载了。因此,你第二种写法 B = A; 时,不会调用到拷贝构造。
问题二:
多个拷贝构造会引发
Warning 1 warning C4521: 'testClass' : multiple copy constructors specified 编译器警告,但不会导致程序运行出现什么太大问题。系统总是可以找到合适的拷贝构造函数调用。
比如:
class testClass { public: int m_iValueA; int m_ivalueB; public: testClass() { m_iValueA = 99; m_ivalueB = 999; } testClass(testClass& A) { m_iValueA = A.m_iValueA; m_ivalueB = A.m_ivalueB + 1; } testClass(const testClass& A) { m_iValueA = A.m_iValueA + 1; m_ivalueB = A.m_ivalueB + 1; } testClass Me(void) const { return *this; } }; int _tmain(int argc, _TCHAR* argv[]) { testClass A; testClass B = A.Me(); // 调用const 拷贝构造 testClass C = A; // 调用普通拷贝构造 printf("ValueA = %d\t ValueB = %d\r\n", B.m_iValueA, B.m_ivalueB); printf("ValueA = %d\t ValueB = %d\r\n", C.m_iValueA, C.m_ivalueB); getchar(); return 0; }
- 已标记为答案 vieri122 2010年2月20日 10:56
-
问题一: 一般来说你使用Visual Studio 的C++编译器cl.exe 编译时, 编译器都会给没有拷贝构造的类型偷偷地添加一个拷贝构造函数。这个拷贝构造函数就叫做默认拷贝构造函数。有一篇文章推荐给你:
http://blog.chinaunix.net/u/24474/showart_183433.html
也就是说如果你没有在testClass 类型中显式的声明一个拷贝构造函数,编译器在编译时就会给你偷偷添加一个,当执行testClass B = A; 时调用的就是这个默认拷贝构造函数。 另外cl.exe 现在也支持结构体和类之间进行赋值,也就是直接执行 B = A; 编译器也是支持的,当然推荐的方式是你自己重载“=” 运算符(operator =)。因为这只是一个cl.exe 编译器的特性,不能担保其他C++编译器如gcc 也支持这个特性(不好意思,我没有查过gcc 是否真的支持)。
拷贝构造都是成员传值的,一般不传递引用。
问题二,我的代码很清楚啊,你放到你的Visual Studio 跑一下就看到了。
按照你的意思,我创建的testClass 有两个拷贝构造函数,一个是以testClass& 为参数的,另一个是const testClass& 为参数的。 Me() 方法是为了返回一个const testClass 类型的对象。当执行testClass B = A.Me(); 时,实际上传入的是const testClass& 类型,因此调用const testClass& 类型的拷贝构造;当执行testClass C = A; 时,调用的就是testClass 类型的拷贝构造。
同时编译器还会告诉你一个拷贝构造函数太多的警告。- 已标记为答案 vieri122 2010年2月20日 10:56
全部回复
-
问题一:
大家都知道只有在创建某个类的实例时,才会自动的调用构造。 第一种写法 MyClass B = A; 在声明了一个MyClass 类型的实例B的同时,同时给B赋值。因此会调用到MyClass 的拷贝构造。 第二种写法: MyClass A,B; // 这一行执行完,B对象就创建成功了,也就是说, 这行代码执行完成后, 系统已经为B调用完成了合适的构造。 B = A; 此时只能去寻找MyClass 是否有合适的运算符重载了。因此,你第二种写法 B = A; 时,不会调用到拷贝构造。
问题二:
多个拷贝构造会引发
Warning 1 warning C4521: 'testClass' : multiple copy constructors specified 编译器警告,但不会导致程序运行出现什么太大问题。系统总是可以找到合适的拷贝构造函数调用。
比如:
class testClass { public: int m_iValueA; int m_ivalueB; public: testClass() { m_iValueA = 99; m_ivalueB = 999; } testClass(testClass& A) { m_iValueA = A.m_iValueA; m_ivalueB = A.m_ivalueB + 1; } testClass(const testClass& A) { m_iValueA = A.m_iValueA + 1; m_ivalueB = A.m_ivalueB + 1; } testClass Me(void) const { return *this; } }; int _tmain(int argc, _TCHAR* argv[]) { testClass A; testClass B = A.Me(); // 调用const 拷贝构造 testClass C = A; // 调用普通拷贝构造 printf("ValueA = %d\t ValueB = %d\r\n", B.m_iValueA, B.m_ivalueB); printf("ValueA = %d\t ValueB = %d\r\n", C.m_iValueA, C.m_ivalueB); getchar(); return 0; }
- 已标记为答案 vieri122 2010年2月20日 10:56
-
问题一: 一般来说你使用Visual Studio 的C++编译器cl.exe 编译时, 编译器都会给没有拷贝构造的类型偷偷地添加一个拷贝构造函数。这个拷贝构造函数就叫做默认拷贝构造函数。有一篇文章推荐给你:
http://blog.chinaunix.net/u/24474/showart_183433.html
也就是说如果你没有在testClass 类型中显式的声明一个拷贝构造函数,编译器在编译时就会给你偷偷添加一个,当执行testClass B = A; 时调用的就是这个默认拷贝构造函数。 另外cl.exe 现在也支持结构体和类之间进行赋值,也就是直接执行 B = A; 编译器也是支持的,当然推荐的方式是你自己重载“=” 运算符(operator =)。因为这只是一个cl.exe 编译器的特性,不能担保其他C++编译器如gcc 也支持这个特性(不好意思,我没有查过gcc 是否真的支持)。
拷贝构造都是成员传值的,一般不传递引用。
问题二,我的代码很清楚啊,你放到你的Visual Studio 跑一下就看到了。
按照你的意思,我创建的testClass 有两个拷贝构造函数,一个是以testClass& 为参数的,另一个是const testClass& 为参数的。 Me() 方法是为了返回一个const testClass 类型的对象。当执行testClass B = A.Me(); 时,实际上传入的是const testClass& 类型,因此调用const testClass& 类型的拷贝构造;当执行testClass C = A; 时,调用的就是testClass 类型的拷贝构造。
同时编译器还会告诉你一个拷贝构造函数太多的警告。- 已标记为答案 vieri122 2010年2月20日 10:56