4

在 C++11 之前,我看到过这样的代码:

class Car {
public:
  Car() {}
private:
  Car(const Car&);
  Car& operator=(const Car&);
};

对于 C++11(及更高版本),我看到如下代码:

class Car {
public:
  Car() {}
private:
  Car(const Car&) = delete;
  Car& operator=(const Car&) = delete;
};

它们的行为是否相同?如果不是,请解释。

参考:https ://ariya.io/2015/01/c-class-and-preventing-object-copy

4

4 回答 4

5

它们在大多数方面相似,但在其他一些方面有所不同。

考虑以下试图复制类对象的外部代码:

int main() {
    Car c;
    Car other{c};
}

这两个版本都会导致上述代码失败。不过,此时,开发人员会查看界面以了解原因。有了这个delete版本,很明显这Car不是要被复制的。有了这个private版本,(至少没有评论),它提出了一个疑问,即复制构造函数是否可能private被意外放置在该部分中。

现在考虑成员代码试图复制类的对象:

void Car::foo() {
    Car c;
    Car other{c}; 
}

delete版本像以前一样失败。private版本是链接错误。这引发了一个更大的疑问——忘记定义已声明的方法并不少见。也许这就是这里发生的事情?delete版本没有这个问题。

编辑Scott Meyers 在Effective Modern C++ Prefer deleted functions to private undefined ones 的第 11 项中讨论了这一点。

于 2016-10-06T05:27:35.953 回答
5

请注意,您发布的两个片段给出了完全相同的错误,类似于:

'Car(const Car&)' 在此上下文中是私有的

这是因为您在这两种情况下都将成员方法定义为私有。
如果您想了解这些差异,您应该拥有 public deleted 复制构造函数和复制运算符,即:

class Car {
public:
  Car() {}
// private: <-- this should not be here
  Car(const Car&) = delete;
  Car& operator=(const Car&) = delete;
};

这样,您将被告知这些成员方法已被明确且有意地删除

使用已删除的函数“Car(const Car&)”

将它们设置为私有并没有明确表示我想删除它们
例如,您可能希望强制类的用户使用工厂方法来创建该类的实例。

无论如何,(不再如此)新功能不是免费的,并且以非预期的方式使用它们不会带来预期的好处

于 2016-10-06T06:18:36.203 回答
5

=delete将给出更有意义的错误信息。有关已删除函数的错误消息告诉您它不存在,并且没有人可以使用所述构造函数创建对象。说它是私人的并没有提供该信息 - 它只是说调用者不能调用它,而不是没有人可以。

此外,如果从类内部/外部调用已删除的构造函数,其行为也不会有所不同(因为可以从类内部调用私有构造函数)。

https://godbolt.org/g/06R9AQ

于 2016-10-06T05:23:53.077 回答
3

Car& operator=(const Car&) = delete;明确表示“禁止复制分配”。

= delete;也可用于 Bjarne博客中描述的任何功能:

struct Z {
    // ...

    Z(long long);     // can initialize with an long long
    Z(long) = delete; // but not anything less
};
于 2016-10-06T05:39:45.440 回答