使用{}初始化对象是好习惯吗? [英] Is it good habit to always initialize objects with {}?
问题描述
使用新的{}语法初始化对象,如下所示:
Initializing objects with new {} syntax like this:
int a { 123 };
有好处 - 你不会声明一个函数而不是错误地创建一个变量。我甚至听说,应该习惯总是这样做。但看看会发生什么:
has benefit - you would not declare a function instead of creating a variable by mistake. I even heard that it should be habit to always do that. But see what could happen:
// I want to create vector with 5 ones in it:
std::vector<int> vi{ 5, 1 }; // ups we have vector with 5 and 1.
这是好习惯吗?有没有办法避免这种问题?
Is this good habit then? Is there a way to avoid such problems?
推荐答案
坦率地说,各种初始化技术的微妙之处使得很难说任何一个做法是一个好习惯。
Frankly, the subtleties of the various initialization techniques make it difficult to say that any one practice is a "good habit."
正如注释中提到的,Scott Meyers在 Modern Effective C ++ 中详细讨论了括号初始化。他在他的博客上进一步评论了这个问题,例如此处和此处。在第二篇文章中,他最后明确地说,他认为C ++初始化变幻莫测的错误只是一种糟糕的语言设计。
As mentioned in a comment, Scott Meyers discusses brace-initialization at length in Modern Effective C++. He has made further comments on the matter on his blog, for instance here and here. In that second post, he finally says explicitly that he thinks the morass of C++ initialization vagaries is simply bad language design.
正如101010的回答中提到的, -初始化。在我看来,防止隐性缩小是主要的好处。 最麻烦的解析问题当然是一个真正的好处,但它是微不足道 - 在我看来,在大多数情况下,一个不正确的 int a();
而不是<
As mentioned in 101010's answer, there are benefits to brace-initialization. The prevention of implicit narrowing is the main benefit, in my opinion. The "most vexing parse" issue is of course a genuine benefit, but it's paltry--it seems to me that in most cases an incorrect int a();
instead of int a;
would probably be caught at compile time.
但是至少有两个主要的缺点:
But there are at least two major drawbacks:
- 在C ++ 11和C ++ 14中,
auto
总是推导std :: initializer_list
。在C ++ 17中,如果初始化列表中只有一个元素,并且=
是不是,则使用auto
推导出该元素的类型;多个元素的行为未更改(请参阅以上链接的第二篇博文,以获得更清楚的说明,并附上示例。)(修改 ,我理解C ++ 17
规则为auto
与大括号初始化仍然 - 101010的第三个列出的好处是,初始化列表构造函数是首选的对所有其他建设者,实际上是一个缺点以及一个好处。你已经提到了
std :: vector< int> vi {5,1};
对于熟悉向量
的旧二元素构造函数的人来说是令人惊讶的。 Scott Meyers列出了有效现代C ++ 中的一些其他示例。个人而言,我发现这甚至比auto
扣除行为(我通常只使用auto
与复制初始化,这使得第一个问题相当容易避免。)
- In C++11 and C++14,
auto
always deducesstd::initializer_list
from a brace-initializer. In C++17, if there's only one element in the initialization list, and=
is not used,auto
deduces the type of that element;the behavior for multiple elements is unchanged(See the second blog post linked above for a clearer explanation, with examples.) ( as pointed out by T.C. in a comment below, my understanding of theC++17
rules forauto
with brace initialization is still not quite right.) All of these behaviors are somewhat surprising and (in mine and Scott Meyers' opinions) annoying and perplexing. - 101010's third listed benefit, which is that initialization list constructors are preferred to all other constructors, is actually a drawback as well as a benefit. You've already mentioned that the behavior of
std::vector<int> vi{ 5, 1 };
is surprising to people familiar withvector
's old two-element constructor. Scott Meyers lists some other examples in Effective Modern C++. Personally, I find this even worse than theauto
deduction behavior (I generally only useauto
with copy initialization, which makes the first issue fairly easy to avoid).
编辑:原来,愚蠢的编译器实现决定有时可以使用括号初始化的另一个原因(虽然真的 #undef
方法可能更正确)。
It turns out that stupid compiler-implementation decisions can sometimes be another reason to use brace-initialization (though really the #undef
approach is probably more correct).
这篇关于使用{}初始化对象是好习惯吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!