代码之家  ›  专栏  ›  技术社区  ›  Francis Cugler

删除复制构造函数和运算符=类作用域访问

  •  1
  • Francis Cugler  · 技术社区  · 7 年前

    在旧版本的C++中 copying 对于类对象,它们通常会声明 Copy Constructor operator=() 在类的私有部分中:

    class Foo {
    public:
        Foo(){} // Default
        ~Foo(){} // Default
    
    private:
        Foo( const Foo& c ); // not implemented
        Foo& operator=( const Foo& c ); // not implemented
    };
    

    这很直截了当。现在有了更新版本的C++,我们可以改为这样做。

    class Foo {
    public:
        Foo() = default;
        ~Foo() = default;
    private:
        Foo( const Foo& c ) = delete;
        Foo& operator=( const Foo& c ) = delete;
    };
    

    我的问题是:用现代的方法,将这些 deleted 功能,如果在其类别的公共、受保护或私有部分中定义,是否重要或有任何区别?


    例如,上述内容与以下内容是否有任何区别:

    class Foo {
    public:
        Foo() = default;
        ~Foo() = default;
        Foo( const Foo& c ) = delete;
        Foo& operator=( const Foo& c ) = delete;
    };
    

    编辑:

    我接受了暗影游侠的回答,因为他们用例子进行了解释,并提供了一个链接 Q/A 这清楚地解释了这些建议以及为什么。。。

    我注意到,在第一个示例中,当它们被声明时 private 您将获得额外的 compiler errors 在已经存在的 编译器错误 声明为时已生成的 public .

    4 回复  |  直到 7 年前
        1
  •  5
  •   ShadowRanger    7 年前

    It has been recommended that the deleted function be public 如果只是为了简化错误消息。例如,on gcc ,当声明已删除的副本构造函数时,错误消息更加详细 private ,但没有提供更多信息,例如 g++ 7,无论哪种方式都会出现此错误:

    deleted_copy.cpp:5:10: error: use of deleted function ‘A::A(const A&)’
        A b = a;
              ^
    In file included from deleted_copy.cpp:1:0:
    deleted_copy.h:6:5: note: declared here
         A(const A&) = delete;
         ^
    

    但是如果复制构造函数是 私有的 ,您还将得到(在上面给出的错误之上;关于删除复制构造函数的错误是最后一个):

    deleted_copy.cpp: In function ‘int main()’:
    deleted_copy.cpp:5:10: error: ‘A::A(const A&)’ is private within this context
        A b = a;
              ^
    In file included from deleted_copy.cpp:1:0:
    deleted_copy.h:6:5: note: declared private here
         A(const A&) = delete;
         ^
    

    在这两种情况下, deleted_copy.cpp 是:

    #include "deleted_copy.h"
    
    int main() {
       A a;
       A b = a;
    }
    

    还有我的 deleted_copy.h 是:

    class A
    {
    public:
        A() = default;
    private:
        A(const A&) = delete;
    };
    

    使用 私有的 当测试其行为时,行被注释掉 平民的 .

        2
  •  2
  •   Hatted Rooster    7 年前

    不,没关系。被删除的构造函数只有在通过重载解析选取后才会导致编译失败。这意味着,如果您删除了私有构造函数,然后尝试在类之外使用这些构造函数,那么在得到删除的构造函数错误之前,您将得到一个访问错误。

    无论哪种方式,无论删除的构造函数是什么范围,对它的任何调用都将以编译错误结束。

        3
  •  1
  •   Stephan Lechner    7 年前

    这并不重要,原因有二:

    第一 delete 避免隐式生成复制构造函数,因此根本不会在私有、公共或任何部分生成复制构造函数。

    其次,如果T具有无法复制的直接基类或虚拟基类(具有已删除、不可访问或不明确的复制构造函数),则将隐式声明或默认的T类复制构造函数定义为已删除;

    所以a deleted 复制构造函数就像并没有复制构造函数一样简单,由于上面的定义,在子类中无法“修复”。

        4
  •  1
  •   aschepler    7 年前

    至于如何使用这个类,这没有什么区别。

    但它可以改变编译器诊断消息。使用g++5.4.0版,我在尝试使用私有和已删除的成员时,遇到了关于访问私有成员的编译器错误和关于使用已删除函数的错误。另一方面,两个不同的clang++版本似乎足够聪明,只显示有关删除函数的消息,而忽略不太相关的私有访问细节。

    所以我更愿意宣布这些成员为公众。函数被删除的事实实际上是您希望在无效使用时显示的,如果编译器也抱怨私有访问,那只是额外的噪音。而且,也许更重要的是,类不可复制和/或不可分配副本这一事实是类的一个关键属性,可能与阅读 public: 部分