默认定义声明的详细程度不完整
Incomplete verbosity of default definitions declarations
在Stroustrup的C++之旅中,他提到:
如果明确某些默认值,则不会生成其他默认定义。
但是,gcc 4.9.1 似乎并非如此。举个例子:
#include <iostream>
using namespace std;
struct A
{
int data;
A() = default;
A(const A&) = default;
};
int main()
{
A a;
a.data = 10;
A b(a);
A c;
c = a;
cout<<b.data<<endl;
cout<<c.data<<endl;
return 0;
}
它编译并给出预期的输出,即已经生成了默认赋值运算符。
我误解了斯特劳斯特鲁普的评论吗?
首先,你的代码不使用类的赋值运算符,所以它不证明它的存在。但是,添加它的用途
c = a;
会起作用,所以问题仍然存在。
声明任何特殊函数并不能阻止生成所有其他特殊函数,这似乎是您解释报价的方式。声明一些会抑制其他一些。没有读过这本书来把这句话放在上下文中,我不能说它是否具有误导性。
规则大致如下:
- 声明任何构造函数将阻止隐式默认构造函数; 声明移动构造函数或移动赋值运算符
- 将阻止隐式复制构造函数和复制赋值运算符;
- 声明析构函数、复制构造函数或复制赋值运算符将阻止隐式移动构造函数和移动赋值运算符;
这是一种简化;还有更多的细微差别和例外。如果您想要血腥的细节,请阅读语言规范。
这些
声明当前是默认生成的(这就是您提供的代码起作用的原因(,但此行为在对C++标准的进一步修订(已弃用(中随时可能被删除。
在Stroustrup的C++11常见问题解答中,他说
如果用户显式指定了任何移动、复制或析构函数(声明、定义、=default 或 =delete(,则默认情况下不会生成任何移动。
这是不言自明的。然而,他接着说...
如果用户显式指定了任何移动、复制或析构函数(声明、定义、=default 或 =delete(,则默认情况下会生成任何未声明的复制操作,但这已弃用,因此不要依赖它。
然后他列举了几个例子:
class X1 {
X1& operator=(const X1&) = delete; // Disallow copying
};
这也隐式地禁止移动 X1。 允许复制初始化,但已弃用。
class X2 {
X2& operator=(const X2&) = delete;
};
这也隐含地禁止移动 X2s。 允许复制初始化,但已弃用。
class X3 {
X3& operator=(X3&&) = delete; // Disallow moving
};
这也隐含地禁止复制 X3。
class X4 {
~X4() = delete; // Disallow destruction
};
这也隐含地禁止移动 X4。 允许复制,但已弃用。
相关文章:
- C++链接时间资源"allocation"而不定义
- 无法使用迭代器查找类对象。(二进制 '==': 'userInfo' 不定义此运算符)
- 基类可以声明虚拟方法但不定义它吗?仍然在派生类中定义
- C++:如何在不定义的情况下声明非函数?
- 为什么C++没有简洁的语法允许在不定义计数器的情况下多次执行操作?
- 是否可以超载[]运算符在不定义类的情况下访问特定的字符
- 如何在不定义目标变量大小的情况下逐个字符将字符串变量复制到另一个字符
- 如何在不定义其他 fonction getValue() 的情况下获取私有值
- C++带有/不定义模板的重载运算符
- 在不定义类的情况下将启动的类传递给函数
- 如何不定义此变量
- 如何在C++中声明一个结构而不定义它
- 有没有办法在不定义模板函数的情况下为不同的 std::array 定义函数
- 为什么/何时使用类数据成员而不定义该类的对象
- 为什么当你不定义函数时,你会得到一个链接器错误而不是编译器?
- 为什么 std::string 不定义乘法或文字?
- 默认定义声明的详细程度不完整
- 不定义专有编译器宏潜伏着什么危险
- 无法在不定义模板变量的情况下声明它
- 有没有一种方法可以在不定义c++基类的情况下创建工厂