【问题标题】:Does signature of custom assignment operator=() matter when I just want to disable it?当我只想禁用它时,自定义赋值 operator=() 的签名是否重要?
【发布时间】:2016-09-27 05:18:50
【问题描述】:

我需要禁用复制赋值运算符。这将起作用:

A& operator=(const A&);

如果我不为 operator= 指定确切的参数,它会起作用吗?
我的意思是这样的:

void operator=(void);

返回值是对的,想写什么都可以,但是参数类型呢?
这会覆盖默认的operator= 类吗?

【问题讨论】:

  • "会起作用吗...";您尝试过吗?
  • 赋值必须只有一个参数。
  • @WhozCraig,是的,我可以试试看它是否有效,但我想知道为什么。

标签: c++ operator-overloading assignment-operator


【解决方案1】:

来自 C++ 标准草案的12.8p17

用户声明的复制赋值运算符X::operator= 是类X 的非静态非模板成员函数,只有一个XX&const X&volatile X& 类型的参数或const volatile X&.

我猜这个回复比任何其他测试或示例代码都要好。

请注意,类似的东西也适用于移动赋值运算符,请参阅12.8p19

用户声明的移动赋值运算符 X::operator= 是 X 类的非静态非模板成员函数,只有一个 X&&、const X&&、volatile X&& 或 const volatile X&& 类型的参数。

这些也证实了,正如您所猜测的,返回值类型并不重要。

【讨论】:

    【解决方案2】:

    这是来自current standard(第 12.8 页第 17 节)的用户声明的复制赋值运算符的精确定义:

    用户声明的复制赋值运算符X::operator= 是非静态的 class X 的非模板成员函数,只有一个参数 键入X, X&, const X&, volatile X&const volatile X&

    注意事项:

    • 重载的赋值运算符必须声明为只有一个 范围;见 13.5.3。
    • 可以为一个类声明不止一种形式的复制赋值运算符。
    • 如果类 X 仅具有带有 X& 类型参数的复制赋值运算符,则无法将 const X 类型的表达式分配给 X 类型的对象。

    例子:

    struct X {
    X();
    X& operator=(X&);
    };
    const X cx;
    X x;
    void f() {
    x = cx; // error: X::operator=(X&) cannot assign cx into x
    }
    

    另外,请使用 C++11 标准中的 delete

    您现在可以将函数设置为默认或已删除。

    您现在可以直接写下您想禁用复制。

    class A {
    A(const A&) = delete;
    A& operator=(const A&) = delete;    // Disallow copying
    };
    

    你也可以明确地通知编译器你想要一个类的默认副本。这样,您可以提供自定义默认构造函数,并且仍然可以从编译器获取其他编译器生成的方法的默认版本。

    class B {
        B(const Y&) = default;
        B& operator=(const B&) = default;   // default copy 
    };
    

    【讨论】:

      【解决方案3】:

      可以有不同类型的任务。只有 copy assignmentmove assignment 可能由编译器生成。如果没有复制/移动分配,则会生成它们。因此,如果您想禁用复制和/或移动分配,则参数类型确实很重要,尽管复制分配可以不同的参数类型具有一定的灵活性。不过,返回类型并不重要。

      class A {
      public:
          void operator=() = delete; // not legal: assignment takes exactly one argument
          void operator=(A) = delete; // OK: copy assignment disabled
          void operator=(A&) = delete; // OK: copy assignment disabled
          void operator=(A const&) = delete; // OK: copy assignment disabled
          void operator=(A&&) = delete; // OK: move assignment disabled
      };
      

      还有一些变体将const 替换为volatileconst volatile 符合复制/移动分配的条件。当您禁用复制分配时,移动分配的自动生成也将被禁用。如果禁用移动分配,我认为仍然会生成复制分配。如果禁用任何不能作为复制或移动分配的内容,仍会生成复制/移动分配。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多