C++ 警告:删除多个副本构造函数时定义了它们
环境:VS2015更新3,64位(调试版)编译 在下面的代码中,如果我取消注释C++ 警告:删除多个副本构造函数时定义了它们,c++,c++11,C++,C++11,环境:VS2015更新3,64位(调试版)编译 在下面的代码中,如果我取消注释Maybe(X&)=delete行,我会得到下面代码和问题标题中提到的警告 现在,我知道,在C++(11?)中有一些规则,它们可能会 显式删除该构造函数已过时。只是,即使在搜索之后 有一段时间,我在网上找不到一条明确的规则,可以证实这一点 如果我只删除Maybe(const X&)=delete,编译器将不会自动生成另一个副本构造函数 因此,我的问题首先是: 谁能指出我在C++规范中的位置,它清楚地定义了 自动生成复制
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
// ...
};
模板
也许是上课吧
{
X*m_刚刚;
公众:
显式可能(常数X&X)
:m_just(新X(X))
{}
也许
:m_just(nullptr)
{}
可能(const-Maybe&&other)
:m_just(其他.m_just)
{
other.m_just=nullptr;
}
Maybe(const Maybe&)=删除;
//如果下面的行未注释,则会产生警告:
//警告C4521:“可能”:指定了多个副本构造函数
//Maybe(Maybe&)=删除;
~Maybe()
{
删除m_just;
m_just=nullptr;
}
//…更多与问题无关的成员和代码
// ...
};
请不要对那门课的整个想法发表评论。这只是我私人实验室里的私人修补……;) >我的C++有点生锈,所以这可能是错误的,但是我认为你不应该甚至有一个非const拷贝构造函数(除了移动构造函数自然地)。p> 如果
a=b
改变b
你会让一些人大吃一惊。也许拷贝构造函数以一种外部不可见的方式更改源代码是合法的,但在这种情况下,我认为最好在常量拷贝构造函数内部使用const\u cast
我认为错误不是关于delete
,而是关于定义多个复制构造函数,这是不允许的。我怀疑,即使允许使用非常量复制构造函数,在语言中也有点麻烦
other.m_just = nullptr;
这一行不应该编译。您的编译器一定有问题,或者您的代码示例不能准确反映您正在编译的内容
无论如何,move构造函数应该采用非常量值引用
注释行根本不是必需的。别提了。如果您定义了复制构造函数(即使已删除),编译器也不会定义其他形式的复制构造函数,因此,如果您不使用该行,就不会有对Self进行非常量引用的构造函数,这意味着重载解析只会选择常量引用的复制构造函数,无论如何都会被删除。编译器只会生成
Maybe(Maybe&)
和Maybe(const Maybe&)
第12.8节第8段列出了选择的条件: 类
X
的隐式声明的复制构造函数将具有
表格X::X(常数X&)
if
的每个直接或虚拟基类X
都有一个复制构造函数,其第一个参数的类型为B
或const B&
,并且const volatile B&
- 对于属于
(或其数组)的类类型M
的所有非静态数据成员,每个此类类类型都有一个副本构造函数,其 第一个参数的类型为X
或const M&
const volatile M&
X::X(X&)
或者更非正式地说,参数将是const
当且仅当需要复制的所有内容都可以“const copy”
删除一个不会导致生成另一个
由于您没有基类,并且您的唯一成员是指针,因此生成的构造函数将是常量类型的,您可以省略导致错误的行 这是一个非常好的例子,我的意图是绝对地、真正地完全地不这样做。如中所示-我不需要任何自动生成的复制构造函数。还没有开始使用赋值运算符…
可能
和可能
是同一回事,因为有一种神秘但有用的机制叫做“注入”。@KerrekSB是的-一旦出现警告,我就将它改为可能
。我很想你主要指的是我的移动构造函数,它不是复制构造函数(至少在我看来)但是是的,我同意这很有趣,我可以在我的移动构造函数中变异const对象而没有警告和错误;)不,移动构造函数很好,我不是在说这个。这是当你取消注释那一行时得到的第二个复制构造函数,这就是问题所在。我保留了move构造函数代码以备不时之需。它编译(和运行)时没有警告,也没有我的编译器出错(在我问题的顶部给出了我的工具链)。也许我应该删除它,以免人们分心。@BitTickler啊,我现在明白了。它是模板类的成员函数,因此编译器永远不会对其进行类型检查,除非它被实例化。(MSVC在检查模板方面非常懒惰。)如果你真的试图移动一个可能,你会得到错误。(用更新2测试,还没有安装U3。)实际上,如果我注释掉我的move构造函数,我的代码不会编译。然而,如果我在内部的mutating语句上设置断点,它就永远不会被击中。。。现在,谁能解释呢?!:)如果没有移动构造函数,它将尝试使用复制构造函数:1>…\usingclangmaybe.cpp(225):错误C2280:'Maybe::Maybe(Maybe&'):尝试