代码之家  ›  专栏  ›  技术社区  ›  Camden Narzt

为什么clang认为我有一个复制构造函数?

  •  1
  • Camden Narzt  · 技术社区  · 9 月前

    我有一个包含以下特殊成员函数的结构体:

    struct MyStruct {
        MyStruct(MyStruct& other) = delete;
    
        MyStruct(MyStruct&& other) = default;
    
        explicit MyStruct(int num) noexcept(false);
    
        explicit MyStruct(MyOtherStructType&& other_type);
    
        ~MyStruct();
    
        auto operator=(MyStruct&& other) noexcept(false) -> MyStruct&;
    }
    

    clang-tidy说:

    Class 'MyStruct' defines a non-default destructor, a copy constructor, a move
    constructor and a move assignment operator but does not define a copy assignment
    operator
    

    由于 hicpp-special-member-functions/cppcoreguidelines-special-member-functions lint,但是我以为我删除了复制构造函数?我错过什么了吗?棉绒有问题吗?

    1 回复  |  直到 9 月前
        1
  •  3
  •   user17732522    9 月前

    一旦您明确表示,五的规则适用于所有其他特殊成员函数 声明 任何特殊的成员函数,而不仅仅是当您为其提供自定义定义时。将函数定义为已删除仍然很重要。

    请注意,将函数定义为删除并不等于完全不声明该函数(无论是隐式还是显式)。定义为delete的函数仍然被声明,并正常参与重载解析。它的唯一含义是,如果重载解析会选择删除的函数,那么重载解析将被视为格式不正确。

    删除复制构造函数时,该规则也应适用的原因是,删除复制构造函数不会阻止复制赋值运算符的隐式定义。

    但是,如果您显式删除了复制构造函数,那么您的类型很可能也不应该在赋值时具有默认的复制语义。五的规则确保您不会忘记为复制赋值运算符声明正确的语义,如果您想要编译器默认值,可以通过将重载定义为 = default .

    就目前而言,写作

    MyStruct x(1);
    MyStruct y = x;
    

    是病态的,但是

    MyStruct x(1);
    MyStruct y(2);
    y = x;
    

    将使用编译器生成的默认复制行为进行编译,如果删除了复制构造函数,这可能对您的类型是错误的。


    此外,复制构造函数或复制赋值运算符应将其参数视为 const 参考。不遵守这个惯例会给你带来问题。因为删除的重载仍然参与重载解析,所以它是否使用仍然很重要 const .