c ++拷贝构造函数签名:重要吗?

kir*_*off 6 c++ copy const copy-constructor

我当前的实现使用了大量具有此语法的复制构造函数

MyClass::Myclass(Myclass* my_class)

它真的(functionnaly)是不同的

MyClass::MyClass(const MyClass& my_class)

为什么?

我被告知第一个解决方案不是真正的复制构造函数.但是,进行更改意味着进行了大量的重构.

谢谢!!!

Luc*_*ore 17

它的不同之处在于第一个不是复制构造函数,而是转换构造函数.它从a转换MyClass*为a MyClass.

根据定义,复制构造函数具有以下签名之一:

MyClass(MyClass& my_class)
MyClass(const MyClass& my_class)
//....
//combination of cv-qualifiers and other arguments that have default values
Run Code Online (Sandbox Code Playgroud)

12.8.复制类对象

2)类X的非模板构造函数是一个复制构造函数,如果它的第一个参数是X&,const X&,volatile X&或const volatile X&,并且没有其他参数或者所有其他参数都有默认参数(8.3 .6).113)[例子:X :: X(const X&)和X :: X(X&,int = 1)是复制构造函数.

编辑:你似乎混淆了两者.

说你有:

struct A
{
   A();
   A(A* other);
   A(const A& other);
};

A a;     //uses default constructor
A b(a);  //uses copy constructor
A c(&a); //uses conversion constructor
Run Code Online (Sandbox Code Playgroud)

它们完全用于不同的目的.

  • @fonjibe当编译器复制时,它使用复制构造函数,而只使用复制构造函数.如果你没有声明一个,编译器会生成一个,它可能不会做你想要的. (4认同)

Ker*_* SB 7

第一个版本不是复制构造函数.就那么简单.它只是另一个构造函数.

一个副本一类的构造函数X必须有签名(X &, ...)(X const &, ...)(X volatile &, ...)(X const volatile &, ...),其中所有参数,但先有默认值,如果它们存在(它不能是一个模板).


也就是说,你应该仔细考虑你违反零规则的原因:大多数设计良好的类都不应该有任何用户定义的拷贝构造函数,拷贝赋值运算符或析构函数,而是依赖于 - 设计成员.你当前的构造函数接受一个指针的事实让我想知道你的代码是否正确行为MyClass x = y;- 比如值得检查.


Ste*_*sop 5

某些语言构造需要复制构造函数:

  • 通过价值传递
  • 按价值返回
  • 复制样式初始化(​​虽然在这种情况下通常省略副本)

如果语言要求复制,并且您提供了复制构造函数,则可以使用它(假设cv资格是正常的).

由于您尚未提供复制构造函数,因此您将获得编译器生成的复制构造函数.这通过复制每个数据成员来工作,即使这对您的班级来说不是正确的事情.例如,如果not-a-copy-constructor显式执行任何深层复制或分配资源,则需要禁止编译器生成的副本.

如果编译器生成的副本适用于您的类,那么您的非复制构造函数几乎是无害的.不过,我认为这不是一个特别好的主意:

void some_function(const MyClass &foo);

MyClass *ptr = new MyClass();
const MyClass *ptr2 = ptr;
some_function(ptr); // compiles, but copies *ptr and uses the copy
MyClass bar(ptr2);  // doesn't compile -- requires pointer-to-non-const
Run Code Online (Sandbox Code Playgroud)

即使假设编译器生成的副本对您的类没有好处,进行必要的更改也不需要进行大量的重构.假设你的非构造函数实际上没有修改其参数指向的对象,所以在修复签名后你有:

MyClass::MyClass(const MyClass* my_class) {
    // maybe treat null pointer specially
    // do stuff here
}
Run Code Online (Sandbox Code Playgroud)

你需要:

MyClass::MyClass(const MyClass& my_class) {
    do_stuff(my_class);
}

MyClass::MyClass(const MyClass* my_class) {
    // maybe treat null pointer specially
    do_stuff(*my_class);
}

MyClass::do_stuff(const MyClass& my_class) {
    // do stuff here
}
Run Code Online (Sandbox Code Playgroud)

您还需要将旧构造函数中的任何初始化程序列表复制到新构造函数中,并my_class根据新指针中不是指针的事实对其进行修改.

删除旧的构造函数可能需要大量重构,因为您必须编辑使用它的任何代码.但是,您不必删除旧的构造函数以修复默认复制构造函数的任何问题.