c++没声明构造函数能生成对象吗】_类中声明特殊函数的基本原则

aeb41e293fefaa24a8f4edcd0f5b5fa2.png

C.21: If you define or =delete any default operation, define or =delete them all

C.21:默认操作要定义就全定义,要禁止就全禁止

Reason(原因)

The special member functions are the default constructor, copy constructor, copy assignment operator, move constructor, move assignment operator, and destructor.特殊的成员函数包括构造函数,拷贝构造函数,拷贝复制运算符,移动构造函数,移动复制运算符和析构函数。

译者注:这些函数都具有管理数据成员生命周期的责任,因此实现还是禁止都需要统一。

The semantics of the special functions are closely related, so if one needs to be declared, the odds are that others need consideration too.特殊函数的语义紧密相关,因此如果一个需要生命,可能其他的也需要考虑。

Declaring any special member function except a default constructor, even as =default or =delete, will suppress the implicit declaration of a move constructor and move assignment operator. Declaring a move constructor or move assignment operator, even as=default or =delete, will cause an implicitly generated copy constructor or implicitly generated copy assignment operator to be defined as deleted. So as soon as any of the special functions is declared, the others should all be declared to avoid unwanted effects like turning all potential moves into more expensive copies, or making a class move-only.定义出默认构造函数之外的所有特殊函数,即使采用=default或者=delete的形式,将会抑制隐式声明移动构造函数和移动赋值运算符。声明移动构造函数或者移动复制运算符,即使采用=default或者=delete的形式,也会引起隐式生成的拷贝构造函数或者拷贝复制运算符被定义为=delete。因此,一旦任何一个特殊函数被声明,其他的都应该被声明以避免多余的效果。例如将所有的潜在移动操作都被变成代价高昂的拷贝操作,或者令这个类变成只移动的。

译者注:关于=default和=delete请参考以下链接:https://mp.weixin.qq.com/s/YgyRdwgkcKdbbmMAbU8Amg

https://mp.weixin.qq.com/s/5yMBZWlKN_7OWhaJD4u_XQ

Example, bad(反面示例)

struct M2 {   // bad: incomplete set of default operationspublic:    // ...    // ... no copy or move operations ...    ~M2() { delete[] rep; }private:    pair* rep;  // zero-terminated set of pairs};void use(){    M2 x;    M2 y;    // ...    x = y;   // the default assignment    // ...}

Given that "special attention" was needed for the destructor (here, to deallocate), the likelihood that copy and move assignment (both will implicitly destroy an object) are correct is low (here, we would get double deletion).假设析构函数需要那个“特殊模式”(这里是释放内存),那么(默认的,译者注)拷贝和移动赋值(都会隐性销毁对象)正确动作的可能性就会很低。

Note(注意)

This is known as "the rule of five" or "the rule of six", depending on whether you count the default constructor.这就是众所周知的"5特殊函数规则"或者"6特殊函数规则",不同之处在于是否将默认构造函数算进来。

Note(注意)

If you want a default implementation of a default operation (while defining another), write =default to show you're doing so intentionally for that function. If you don't want a default operation, suppress it with =delete.如果需要默认操作的默认实现(如果定义了其他非默认的),通过=default表示你是有意那么做的。如果不想要默认操作,通用=delete抑制它的产生。

译者注:例如,如果定义了某种形式的构造函数,编译器就不会生成默认的。

Example, good(示例)

When a destructor needs to be declared just to make it virtual, it can be defined as defaulted. To avoid suppressing the implicit move operations they must also be declared, and then to avoid the class becoming move-only (and not copyable) the copy operations must be declared:

如果需要声明是就直接定义为virtual,这个做法可以作为默认。为了避免抑制隐式的移动操作,它们也必须被声明。为了避免类成为只移动(和拷贝禁止)类型,拷贝操作也必须声明:

class AbstractBase {public:  virtual ~AbstractBase() = default;  AbstractBase(const AbstractBase&) = default;  AbstractBase& operator=(const AbstractBase&) = default;  AbstractBase(AbstractBase&&) = default;  AbstractBase& operator=(AbstractBase&&) = default;};

Alternatively to prevent slicing as per C.67, the copy and move operations can all be deleted:为了避免由于规则C.67产生的分歧,也可以将拷贝和移动运算符定义为删除的。

class ClonableBase {public:  virtual unique_ptr clone() const;  virtual ~ClonableBase() = default;  ClonableBase(const ClonableBase&) = delete;  ClonableBase& operator=(const ClonableBase&) = delete;  ClonableBase(ClonableBase&&) = delete;  ClonableBase& operator=(ClonableBase&&) = delete;};

Defining only the move operations or only the copy operations would have the same effect here, but stating the intent explicitly for each special member makes it more obvious to the reader.只定义移动操作或者拷贝操作会产生同样的效果,但是应该明确地为每个特殊函数说明目的以便让读者更容易理解。

Note(注意)

Compilers enforce much of this rule and ideally warn about any violation.编译器会强制执行本规则的大部分,理想情况会对任何违反发出警告。

Note(注意)

Relying on an implicitly generated copy operation in a class with a destructor is deprecated.强烈反对一个具有析构函数的类依靠隐式产生的拷贝操作。

Note(注意)

Writing the six special member functions can be error prone. Note their argument types:同时写6个特殊成员函数容易发生错误。注意以下代码中的参数类型。

class X {public:    // ...    virtual ~X() = default;            // destructor (virtual if X is meant to be a base class)    X(const X&) = default;             // copy constructor    X& operator=(const X&) = default;  // copy assignment    X(X&&) = default;                  // move constructor    X& operator=(X&&) = default;       // move assignment};

A minor mistake (such as a misspelling, leaving out a const, using & instead of &&, or leaving out a special function) can lead to errors or warnings. To avoid the tedium and the possibility of errors, try to follow the rule of zero.小错误(例如拼写错误,落了const,用了&而不是&&,或者落了某个特殊成员函数)会引起错误或警告。为了避免无聊的代码和可能的错误,努力践行"0特殊函数"原则。

Enforcement(实施建议)

(Simple) A class should have a declaration (even a =delete one) for either all or none of the special functions.(简单)类应该要么声明(哪怕是通过=delete)所有的特殊函数,要么一个也声明。

原文链接:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all


觉得本文有帮助?请分享给更多人。

更多文章请关注微信公众号【面向对象思考】!

面向对象开发,面向对象思考!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值