C++值传递函数参数时对象构造机制及拷贝构造函数必要性问询
关于C++按值传参时对象构造的疑问解答
嘿,从C转C++刚接触类和对象的话,碰到这个拷贝构造的问题太正常了,我来给你理清楚~
1. 函数里的arg是怎么构造的?
你观察得很仔细:确实没看到你自定义的构造函数输出,但对象arg确实被创建了——这是因为编译器自动为你的类生成了一个默认拷贝构造函数。
这个默认拷贝构造函数你没显式写出来,但它会在按值传递对象、用一个对象初始化另一个对象这类场景下自动调用。它的行为是逐成员拷贝:把原对象(也就是你代码里的obj)的每个成员变量的值,原样复制到新对象arg中。对于你的MyClass来说,就是把obj.a的值(10)复制给arg.a,本质上和你说的“简单内存拷贝”是一回事(因为成员是基本类型int)。
之所以没看到构造函数的输出,是因为这个默认生成的拷贝构造函数不会执行你自定义构造函数里的打印语句,它是默默完成拷贝工作的。
2. 是否最好总是定义拷贝构造函数?
答案是不需要,分情况而定:
- 如果你的类只包含基本类型成员(比如
int、char、bool),没有动态分配的资源(比如用new申请的内存、文件句柄等),那编译器生成的默认拷贝构造完全够用,没必要自己写。就像你例子里的MyClass,默认拷贝构造就能正确完成对象复制,不会有问题。 - 但如果你的类持有动态分配的资源(比如成员是
char*,在构造函数里new了一块内存存储字符串),那默认拷贝构造就会引发问题:它只会拷贝指针的地址,导致原对象和新对象指向同一块内存,当两个对象析构时,会重复释放同一块内存,触发未定义行为。这种情况下,你必须自己实现深拷贝版本的拷贝构造函数,为新对象分配独立的内存,并把原对象的内容复制过去。 - 另外,如果你的类设计上就不应该被拷贝(比如某些单例类、管理独占资源的类),那你可以主动禁用拷贝构造:在C++11及以后,可以用
MyClass(const MyClass&) = delete;来显式禁止;更早的标准可以把拷贝构造声明为private且不实现。
再回到你的代码例子:当你调用myfoo(obj)时,编译器用默认拷贝构造创建了arg,函数执行完后arg离开作用域,析构函数被调用,所以你看到了Destructor call的输出。
内容的提问来源于stack exchange,提问作者Stef1611
相关产品推荐
相关产品推荐

