警告:删除它们时定义了多个复制构造函数

时间:2016-10-24 09:34:28

标签: c++ c++11

环境:VS2015更新3,64位(调试|发布)编译

在下面的代码中,如果我取消注释Maybe(X&) = delete行,我会收到以下代码和问题标题中提到的警告。

现在,我知道,C ++中有一些规则(11?),可能会呈现 显式删除该构造函数已过时。只有在搜索之后 网络一段时间,我找不到一个明确的规则,这将证实,那 如果我只删除Maybe(const X&) = delete,编译器将不会自动生成其他复制构造函数。

所以我的问题首先是: 任何人都可以指出我在C ++规范中发现,它明确定义了 自动生成复制构造函数的规则?或者,一些不太官方 容易记住关于如何确定将会发生什么的经验也是受欢迎的。

template <class X>
class Maybe
{
    X *m_just;
public:
    explicit Maybe(const X& x)
        : m_just(new X(x))
    {}
    Maybe()
        : m_just(nullptr)
    {}
    Maybe(const Maybe<X>&& other)
        : m_just(other.m_just)
    {
        other.m_just = nullptr;
    }
    Maybe(const Maybe<X>&) = delete;
    // If line below is uncommented, this produces the warning: 
    // warning C4521: 'Maybe<Int32>': multiple copy constructors specified
    // Maybe(Maybe<X>&) = delete; 

    ~Maybe()
    {
        delete m_just;
        m_just = nullptr;
    }
    // ... more members and code which are not related to question
    // ...
};

请不要评论该课程的整个想法。这只是我私人实验室的私人修修补补......;)

3 个答案:

答案 0 :(得分:3)

编译器只会生成Maybe(Maybe<X>&)Maybe(const Maybe<X>&)之一 选择条件列于第12.8节第8节:

  

X的隐式声明的复制构造函数将具有   表格X::X(const X&)如果

     
      
  • B的每个直接或虚拟基类X都有一个复制构造函数,其第一个参数的类型为const B&const volatile B&,并且
  •   
  • 对于X(或其数组)的class type M的所有非静态数据成员,每个这样的类类型都有一个复制构造函数,其中   第一个参数的类型为const M&const volatile M&
  •   
     

否则,隐式声明的复制构造函数将具有该表单   X::X(X&)

或者更非正式地,当且仅当需要复制的所有内容都可以被“复制”时,参数才是const

删除一个不会导致生成另一个。

由于您没有基类且您的唯一成员是指针,因此生成的构造函数将是const类型,您可以省略导致错误的行。

答案 1 :(得分:0)

我的C ++有点生疏,所以这可能是错的,但我认为你甚至不应该有一个非const复制构造函数(自然除了移动构造函数)。

如果a = b更改b,您会让某些人感到惊讶。也许复制构造函数以一种不在外部可见的方式更改源代码是合法的,但在这种情况下,我认为最好在const复制构造函数中使用const_cast

我认为错误不是delete,而是关于定义多个拷贝构造函数,这是不允许的。我怀疑甚至允许非const复制构造函数在语言中有点蠢。

答案 2 :(得分:0)

other.m_just = nullptr;

此行不应编译。你的编译器肯定有问题,或者你的代码示例并没有完全反映你正在编译的内容。

无论如何,移动构造函数应该采用非const 右值引用。

注释行根本不是必需的。把它留下来吧。如果您定义了复制构造函数(即使已删除),编译器也不会定义其他形式的复制构造函数,因此如果您将该行保留,则根本没有构造函数对Self进行非const引用,这意味着重载解析只会选择const引用复制构造函数,无论如何都会删除它。