移动语义对于RAII类非常有用。它们允许人们进行编程,就好像一个人具有有价值的语义,而无需付出繁重的工作。一个很好的例子是从一个函数返回std :: vector。但是,使用值语义进行编程意味着,人们希望类型表现得像原始数据类型一样。有时这两个方面似乎是矛盾的。
一方面,在RAII中,人们会期望默认构造函数返回完全初始化的对象,或者如果资源获取失败则抛出异常。这保证了任何构造的对象都将处于有效且一致的状态(即可以安全使用)。
另一方面,使用移动语义时,存在对象处于有效但未指定状态的情况。同样,原始数据类型可以处于未初始化状态。因此,使用值语义,我希望默认构造函数在此有效但未指定的状态下创建一个对象,以便以下代码具有预期的行为:
// Primitive Data Type, Value Semantics
int i;
i = 5;
// RAII Class, Move Semantics
Resource r;
r = Resource{/*...*/}
在这两种情况下,我都希望“大量”初始化仅发生一次。我想知道,关于此的最佳做法是什么?显然,第二种方法存在一个实际的问题:如果默认构造函数以未指定状态创建对象,那么如何编写一个确实可以获取资源但不带有其他参数的构造函数呢?(想到了标签分派...)
编辑:一些答案对试图使您的类像原始数据类型一样工作的理由提出了质疑。我的一些动力来自Alexander Stepanov的《带组件的高效编程》,他在其中谈论了常规类型。特别地,让我引用:
在c中[对于内置类型],自然的惯用语表达应该是对于常规类型的自然的惯用语表达。
他继续提供与上述几乎相同的示例。在这种情况下他的观点无效吗?我理解不对吗?
编辑:由于没有太多讨论,我将接受投票率最高的答案。在默认构造函数中以“ moved-from like”状态初始化对象可能不是一个好主意,因为同意现有答案的每个人都不会期望这种行为。
但是,使用值语义进行编程意味着,人们希望类型表现得像原始数据类型一样。
关键字“喜欢”。不是“相同地”。
因此,使用值语义,我希望默认构造函数在此有效但未指定的状态下创建一个对象
我真的不明白为什么您应该期望这一点。对我来说,这似乎不是一个非常理想的功能。
关于此的最佳实践是什么?
忘记这样一个想法,即非POD类应该与原始数据类型共享此功能。头错了。如果没有明智的方法来初始化没有参数的类,则该类不应具有默认构造函数。
如果您想声明一个对象,但不愿初始化它(可能在更深的范围内),请使用std::unique_ptr
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句