N3797::8.4.2/4 [dcl.fct.def.default]
有以下引用:
如果函数是用户声明的而非显式的,则用户提供该函数 在第一次声明中违约或删除。用户提供的 明确默认的功能(即明确违约后的功能) 第一个声明)是在明确的地方定义的 违约; 如果将此类函数隐式定义为已删除,则为 程序格式不正确。
我试图发明一个反映该规则的例子。因为,标准说:
如果类定义未明确声明副本 构造函数,一个是隐式声明的。如果是类定义 声明一个移动构造函数或移动赋值运算符, 隐式声明的复制构造函数定义为已删除;
以下代码应抛出有关已删除函数调用的错误:
#include <iostream>
using namespace std;
struct A
{
A(){ }
A(const A&&){ cout << "A(const&&)" << endl; }
A(const A&) = default;
};
A a;
A b = a;
int main() {
}
但它运作正常。你能提供反映这一点的实际例子吗?
答案 0 :(得分:1)
以下示例对此进行了解释:
class A {
public:
A(int a) : m_a(a) {}
const int m_a;
};
由于m_a是const成员,所以编译器会隐式删除副本分配运算符函数A& operator=(const A&)
。所以你不能做以下事情
int main() {
A var1(1);
A var2(3);
var2 = var1;
}
您应该会遇到copy assignment operator implicitly deleted
这样的编译时错误。现在,您将很容易明确地将其默认设置
class A {
public:
A(int a) : m_a(a) {}
A& operator=(const A& other) = default;
const int m_a;
};
您仍然会遇到编译时错误,并且可能会看到类似explicitly defaulted function was implicitly deleted
的消息。但是,如果您绝对需要赋值运算符说要复制其他非const成员,则可以按如下所示明确定义它。
class A {
public:
A(int a) : m_a(a) {}
A& operator=(const A& other) {
m_b = other.m_b;
}
const int m_a;
int m_b = 0;
};
我认为背后的原因很明显。在构造过程中初始化const变量(以及不可复制的成员)后,我们无法重新分配它们。尽管可能会争辩到应该允许默认行为,即仅复制非const(和可复制)成员。但是对于那些不了解这种行为的人,可能会误以为const成员(且不可复制)也被重新分配,从而导致各种错误。
答案 1 :(得分:0)
我的其他答案不正确。在您的情况下,A
的copy-constructor不是用户提供的,因为它在第一次声明时被明确默认。用户提供的显式默认函数如下所示:
struct X
{
X();
};
X::X() = default;
该子句与构造函数在默认情况下被隐式删除的时间有关。举个例子:
struct X
{
X(X&&); // user-declared move-constructor, deletes X's copy-constructor
};
struct Y
{
X x; // data member with deleted copy-constructor deletes Y's
// copy-constructor
Y(Y const&);
};
// program is ill-formed. Y's copy-constructor was implicitly deleted
Y::Y(Y const&) = default;
由于X
具有隐式删除的复制构造函数,因此Y
具有隐式删除的复制构造函数,因为x
是其数据成员。在声明构造不正确后明确默认构造函数。