【问题标题】:Why would you =delete implicitly deleted default constructors and what is the point?你为什么要 =delete 隐式删除的默认构造函数,这有什么意义?
【发布时间】:2019-07-22 15:10:23
【问题描述】:

我正在尝试删除所有隐式提供的复制/移动 ctor/赋值运算符,但为什么我仍然能够显式删除应该隐式删除的默认 ctor?

我尝试了 =default-ing 隐式提供的所有复制/移动 ctor/assignment 运算符,然后才被告知实际 =delete 而不是 =default。如果我对隐式/显式的理解是正确的,那么如果用户提供了显式的复制 ctor,则默认的 ctor 应该被隐式删除。

我有以下课程:

class A {
public:
   A() =delete;       
   A(const A&):...{;} --> my explicitly defined copy ctor
   ...
}

我希望编译器告诉我我不能 =delete 隐式删除的默认 ctor,但事实并非如此。我正在使用clang8进行编译。

【问题讨论】:

  • 告诉编译器你想删除它无论如何都会删除的东西会有什么问题?
  • 我有很多基类和子类,在处理继承和 const 成员变量时,我试图删除尚未删除的内容,以建立规范以施加限制。我不希望下一个程序员必须查找继承链来尝试找出尚未隐式删除的内容。
  • 如果编译器没有生成函数,它不会被用作可能的匹配。如果你明确地=delete 一个函数,它仍然可能被认为是可能的最佳匹配,然后编译器会出错,说函数已被删除。

标签: c++ clang


【解决方案1】:

您可以简单地删除您想要的所有内容,无论是否已经(隐式)删除,完全独立。

最好表明您不想使用默认生成的函数(如运算符或构造函数)并将它们“标记”为已删除。这有助于澄清界面!

但是:即使你删除了构造函数,你仍然可以实例化你的类!

class A { 
    public:
        A() =delete;
        A(int) = delete;

        int a;

        void Print() const { std::cout << a << std::endl; }
};  

int main()
{   
    A a{42};
    a.Print();
}  

见:https://en.cppreference.com/w/cpp/language/aggregate_initialization

来自您的评论:

我不希望下一个程序员必须查找继承链来尝试找出尚未隐式删除的内容。

只要你定义了一个构造函数并且没有显式地启用基构造函数的使用:

 using X::X;

根本没有人需要查看基类构造函数。如前所述:将“不需要的”方法标记为 delete 是个好主意,但在某些情况下,这在任何情况下都没有帮助,如上所示!

【讨论】:

  • 有趣的是,在阅读了您的答案后,我返回并从复制 ctor 中删除了初始化列表,编译器抱怨我正在删除已删除的构造函数。但是,如果我将复制 ctor 保留为初始化列表,编译器将提供一个默认 ctor,并且当我尝试删除默认 ctor 时我不会收到任何投诉。我不确定为什么会这样,这是编译器的预期行为吗?嗯
  • @AlexB:关于从 c++11 到 c++20 的“删除”事情,有一个(无穷无尽的)讨论列表。尤其是关于可以通过删除所有构造函数来实例化的聚合是一个非常“好”的特性。我无法告诉您 iso 委员会真正认为什么是“预期行为”;)我只能向您指出非常清晰但不是很直观的标准。
  • 这是一个相当模糊的主题,我希望标准变得更加直观,这样我就不必花几个小时查看 stackoverflow/c++coreGuide 以获得一些解释:)
猜你喜欢
  • 2018-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-24
  • 1970-01-01
  • 2018-10-05
  • 1970-01-01
相关资源
最近更新 更多