C++11 中默认函数有什么意义?
-
05-07-2019 - |
解决方案
默认构造函数将具有声明,并且该声明将受到正常访问规则的约束。例如。您可以使默认的复制构造函数受到保护。如果没有这些新声明,默认生成的成员将是公共的。
其他提示
Stroustrup的网站中的这些示例可能有助于您理解这一点:
默认和删除的功能 - 控制默认值
“禁止”的常用习语 复制"现在可以表达出来 直接:
class X { // ... X& operator=(const X&) = delete; // Disallow copying X(const X&) = delete; };
相反,我们也可以明确说出来 我们想要默认的复制行为:
class Y { // ... Y& operator=(const Y&) = default; // default copy semantics Y(const Y&) = default; };
明确默认是 显然多余,但评论 这种影响和(更糟糕的)用户 明确定义复制操作 意味着给出默认行为 并不罕见。离开它 编译器实现默认值 行为更简单,更不容易出错, 并经常导致更好的目标代码。 “默认”是指“默认”。可以使用机制 对于任何具有默认值的函数。 “删除”机制可以用于 任何功能。例如,我们可以 消除不希望的转换,如 这样:
struct Z { // ... Z(long long); // can initialize with an long long Z(long) = delete; // but not anything less };
除了更改生成函数的可访问性(私有/受保护)之外,您还可以使它们虚拟化。
struct S
{
virtual ~S();
virtual S& operator=(const S&);
};
S::~S() = default;
S& S::operator=(const S&) = default;
可以修改默认功能的以下方面:
- 访问(非公开)
- 虚拟的
- 显式(构造函数)
- 异常规范
- 参数的常量性
但要做到这一点,函数必须在类之外定义(8.4.2/2 中 C++0x 最终委员会草案).
劳伦斯·克劳尔 (Lawrence Crowl) 原始提案的一个版本是 这里.
谢谢 罗杰·佩特 用于澄清和引用。
1)隐式生成的析构函数目前不是虚拟的。所以你需要定义它们以使它们成为虚拟的,在这种情况下它们不那么有效。使用= default,您将同时拥有virtual和efficent作为隐式生成的析构函数。
2)他们将拥有访问说明符,与隐式生成的说明符相反。
3)如果你内联你的默认构造函数,你的课仍然是微不足道的。
我怀疑能够默认生成复制构造函数实际上是有用的。我看不到默认生成默认构造函数的用法,因为你说你输入的实现会更短。
请参阅 Scott Meyer 的伟大著作中的第 17 条“有效的现代 C++”。它描述了生成(或不生成)默认复制构造函数、复制操作和移动操作的许多条件。
换句话说,编译器可能不会“无论如何都这样做”。但是,如果默认的特殊成员函数有意义,则用户可以使用“default”关键字显式告诉编译器生成默认函数,否则不会生成该默认函数。
第 17 条末尾的“要记住的事情”:
仅针对缺少显式声明的移动操作、复制操作或析构函数的类生成移动操作。
复制构造函数仅针对缺少显式声明的复制构造函数的类生成,并且如果声明了移动操作,则复制构造函数将被删除。复制赋值运算符仅针对缺少显式声明的复制赋值运算符的类生成,并且如果声明了移动操作,则该运算符将被删除。不推荐在具有显式声明的析构函数的类中生成复制操作。
对我来说,它的禁用功能非常有用,对于我目前创建的大多数类,我禁用了复制和放大功能。赋值 - 拥有编译器可以识别的功能,而不是依赖于链接器错误,这将是很好的。
如果您有一个包含大量属性的类,则默认对复制构造函数更有用。 例如,如果您有这个类:
class MyClass {
private:
int offset;
std::string name;
std::vector<Person*> relatives;
float weight;
MyClass* spouse;
Vehicle* car;
double houseArea;
Date birth;
Person* parents[2];
public:
/* Default constructor will be defined here */
};
而不是以这种方式定义复制构造函数:
MyClass(const MyClass& that) :
offset(that.offset),
name(that.name),
relatives(that.relatives),
weight(that.weight),
spouse(that.spouse),
car(that.car),
houseArea(that.houseArea),
birth(that.birth),
parents(that.parents)
{}
你会这样定义:
MyClass(const MyClass&) = default;