Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;复制构造函数签名:这有关系吗_C++_Copy_Constants_Copy Constructor - Fatal编程技术网

C++ c++;复制构造函数签名:这有关系吗

C++ c++;复制构造函数签名:这有关系吗,c++,copy,constants,copy-constructor,C++,Copy,Constants,Copy Constructor,我当前的实现使用了大量具有这种语法的复制构造函数 MyClass::MyClass(MyClass*myu class) 它真的(功能)不同于 MyClass::MyClass(const MyClass&my\u class) 为什么 我被告知第一个解决方案不是真正的复制构造函数。然而,进行更改意味着相当多的重构 谢谢 不同的是,第一个不是复制构造函数,而是转换构造函数。它从MyClass*转换为MyClass 根据定义,副本构造函数具有以下签名之一: MyClass(MyClass&

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

MyClass::MyClass(MyClass*myu class)

它真的(功能)不同于

MyClass::MyClass(const MyClass&my\u class)

为什么

我被告知第一个解决方案不是真正的复制构造函数。然而,进行更改意味着相当多的重构


谢谢

不同的是,第一个不是复制构造函数,而是转换构造函数。它从
MyClass*
转换为
MyClass

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

MyClass(MyClass& my_class)
MyClass(const MyClass& my_class)
//....
//combination of cv-qualifiers and other arguments that have default values
12.8. 复制类对象 2) 类X的非模板构造函数是复制构造函数,如果 第一个参数的类型为X&、常量X&、volatile X&或常量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
MyClass::MyClass(const MyClass* my_class) {
    // maybe treat null pointer specially
    // do stuff here
}
它们一起用于不同的目的。

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

X
的副本构造函数必须具有签名
(X&,…)
(X常量&,…)
(X volatile&,…)
(X const volatile&,…)
,其中除第一个参数外的所有参数都具有默认值(并且必须不是模板)



也就是说,您应该仔细考虑为什么违反零规则:大多数设计良好的类根本不应该有任何用户定义的复制构造函数、复制赋值运算符或析构函数,而是依赖于设计良好的成员。您当前的构造函数带有指针这一事实让我怀疑您的代码是否正常工作对于类似于
MyClass x=y;
的内容,这是正确的-值得检查。

第一个示例不是复制构造函数。这意味着,当您提供它时,编译器仍然为您提供一个默认的复制构造函数,其签名等效于

MyClass(const MyClass& my_class);
如果您正在对构造函数执行一些特殊的操作,并且编译器提供的复制构造函数不遵循该逻辑,那么您应该实现一个复制构造函数,或者找到一种禁用它的方法

为什么我要使用复制构造函数而不是转换构造函数

如果将
MyClass
对象提供给一些希望复制构造函数有效的代码,则可能会出现问题

STL容器就是这种情况。例如,如果您使用
std::vector
,您必须知道允许向量使用其复制构造函数移动元素以进行重新分配


编译器提供的默认构造函数将执行浅层复制,调用每个属性的复制构造函数,为基本类型(如指针)创建简单副本。如果需要某种形式的深度复制,则必须正确重写MyClass的复制构造函数。
某些语言构造需要复制构造函数执行官:

  • 按值传递
  • 按值返回
  • 复制样式初始化(尽管在这种情况下通常省略复制)
如果语言需要一个副本,并且您提供了一个副本构造函数,那么就可以使用它(当然,假设简历资格是可以的)

由于您没有提供复制构造函数,因此您将获得编译器生成的复制构造函数。这通过复制每个数据成员来实现,即使这对您的类来说不是正确的操作。例如,如果您的非复制构造函数显式执行任何深度复制或分配资源,则需要抑制编译器-g生成的副本

如果编译器生成的副本适用于您的类,那么您的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
即使假设编译器生成的副本对您的类没有好处,进行必要的更改也不需要进行大量重构。假设您的not-a-constructor没有实际修改其参数所指向的对象,那么在修复签名后,您有:

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
MyClass::MyClass(const MyClass* my_class) {
    // maybe treat null pointer specially
    // do stuff here
}
你需要:

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
}
您还需要将任何初始值设定项列表从旧构造函数复制到新构造函数中,并对其进行修改,因为
my_class
不是新构造函数中的指针


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

为什么我更喜欢复制构造函数而不是转换构造函数?缺点、陷阱是什么?@fonjibe th它们是不同的。如果你想将指针转换为
MyClass
,你不需要一个复制构造函数。不明白为什么它有不同的用途:我总是可以实现复制构造函数,拥有一个
*MyClass myc\u ptr
并通过MyClass(*myc\u ptr)复制它。你能顺便确认一下这是正确的吗?谢谢!这也是为什么你更喜欢汽车而不是剪刀的原因。它们做的不是同一件事。例如,复制构造函数将在STL容器/算法操作中使用,而另一个在那里是无用的。@fonjibe当编译器复制时,它使用一个复制构造函数,只有一个复制构造函数构造函数。如果您不声明一个,编译器将生成一个,它可能不会执行您想要的操作。请注意,模板化的构造函数可能不算作复制构造函数(例如,用于确定是否需要生成复制构造函数),但很可能会选择它们来执行“复制”,这是
t&
构造函数经常遇到的难题(