Is it good habit to always initialize objects with {}?

爱⌒轻易说出口 提交于 2019-12-18 08:58:33

问题


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?


回答1:


Frankly, the subtleties of the various initialization techniques make it difficult to say that any one practice is a "good habit."

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.

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:

  • In C++11 and C++14, auto always deduces std::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.) (Edit: as pointed out by T.C. in a comment below, my understanding of the C++17 rules for auto 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 with vector's old two-element constructor. Scott Meyers lists some other examples in Effective Modern C++. Personally, I find this even worse than the auto deduction behavior (I generally only use auto with copy initialization, which makes the first issue fairly easy to avoid).

EDIT: 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).




回答2:


Initializing objects with list initialization should be preferred wherever applicable, because:

  1. Among other benefits list-initialization limits the allowed implicit narrowing conversions.

    In particular it prohibits:

    • conversion from a floating-point type to an integer type
    • conversion from a long double to double or to float and conversion from double to float, except where the source is a constant expression and overflow does not occur.
    • conversion from an integer type to a floating-point type, except where the source is a constant expression whose value can be stored exactly in the target type.
    • conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type.
  2. Another benefit is that is immune to most vexing parse.
  3. Also, initialization list constructors are preferred over other available constructors, except for the default.
  4. Also, they're widely available, all STL containers have initialization list constructors.

Now concerning your example, I would say with knowledge comes power. There's a specific constructor for making a vector of 5 ones (i.e., std::vector<int> vi( 5, 1);).



来源:https://stackoverflow.com/questions/33444814/is-it-good-habit-to-always-initialize-objects-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!