【发布时间】:2015-02-08 18:49:18
【问题描述】:
在 C++ 11 中,新的通用初始化语法也可用于调用普通的构造函数(不带 initializer_list 参数)。虽然看起来还不错,但我认为这可能会导致实际使用中出现问题。
所以假设在我的项目中我使用了一个带有以下类的库:
class Foo
{
public:
Foo(int size, int value); // create 'size' number of elements
Foo(initializer_list<int> list); // create elements as in 'list'
}
在项目中是这样使用的:
Foo foo{10, 2}; // initialize foo with 2 elements: 10 and 2
现在库有了一个新版本,在新版本中作者删除了第二个构造函数,该构造函数采用 initializer_list(有意或错误)。我没有注意到变化,我的项目像以前一样愉快地构建,只是初始化了一个意外的 foo(现在它是 10 个元素而不是 2 个)。
这个问题的另一个版本是 Foo 只有第一个构造函数,你使用通用初始化语法来初始化 foo,现在作者决定添加第二个构造函数,这同样导致 foo 用不同的元素初始化没有被注意到。
只是想知道其他人对此的看法。这是一个真正的问题还是我太担心了?有什么解决方案可以防止这种情况发生吗?谢谢。
【问题讨论】:
-
反对将其视为“通用”并试图普遍使用它当然是一个很好的论据。使用正确的名称“列表初始化”,并且仅在您特别想从列表中初始化时使用它。或者当语法迫使你这样做时,例如类内初始化,或避免令人烦恼的解析。 (但这只是我的意见,不是答案,因为没有真正的答案。)
-
Scott Meyers 在 Effective Modern C++ 的第 7 项中很好地介绍了这一点,是的,这是一个真正的问题。
-
非常酷的问题。有人可以解释为什么允许跳过括号
()吗? -
跟随@ShafikYaghmour:要点是,当使用大括号时,编译器肯定会更喜欢初始化列表构造。事实上,std::vector 有这个确切的问题。当存在这样的构造函数时,必须非常小心地使用
()与{} -
@Angew。我应该更清楚地表述它。为什么决定允许这样做?什么目的?如果第一个必须用
foo(10,2)初始化,第二个用foo({10,2})初始化,就不会有问题。