环境: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
// ...
};
请不要评论该课程的整个想法。这只是我私人实验室的私人修修补补......;)
答案 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引用复制构造函数,无论如何都会删除它。