Do the parentheses after the type name make a difference with new?

后端 未结 6 1078
余生分开走
余生分开走 2020-11-21 04:15

If \'Test\' is an ordinary class, is there any difference between:

Test* test = new Test;

and

Test* test = new Test();
         


        
6条回答
  •  南旧
    南旧 (楼主)
    2020-11-21 05:02

    The rules for new are analogous to what happens when you initialize an object with automatic storage duration (although, because of vexing parse, the syntax can be slightly different).

    If I say:

    int my_int; // default-initialize → indeterminate (non-class type)
    

    Then my_int has an indeterminate value, since it is a non-class type. Alternatively, I can value-initialize my_int (which, for non-class types, zero-initializes) like this:

    int my_int{}; // value-initialize → zero-initialize (non-class type)
    

    (Of course, I can't use () because that would be a function declaration, but int() works the same as int{} to construct a temporary.)

    Whereas, for class types:

    Thing my_thing; // default-initialize → default ctor (class type)
    Thing my_thing{}; // value-initialize → default-initialize → default ctor (class type)
    

    The default constructor is called to create a Thing, no exceptions.

    So, the rules are more or less:

    • Is it a class type?
      • YES: The default constructor is called, regardless of whether it is value-initialized (with {}) or default-initialized (without {}). (There is some additional prior zeroing behavior with value-initialization, but the default constructor is always given the final say.)
      • NO: Were {} used?
        • YES: The object is value-initialized, which, for non-class types, more or less just zero-initializes.
        • NO: The object is default-initialized, which, for non-class types, leaves it with an indeterminate value (it effectively isn't initialized).

    These rules translate precisely to new syntax, with the added rule that () can be substituted for {} because new is never parsed as a function declaration. So:

    int* my_new_int = new int; // default-initialize → indeterminate (non-class type)
    Thing* my_new_thing = new Thing; // default-initialize → default ctor (class type)
    int* my_new_zeroed_int = new int(); // value-initialize → zero-initialize (non-class type)
         my_new_zeroed_int = new int{}; // ditto
           my_new_thing = new Thing(); // value-initialize → default-initialize → default ctor (class type)
    

    (This answer incorporates conceptual changes in C++11 that the top answer currently does not; notably, a new scalar or POD instance that would end up an with indeterminate value is now technically now default-initialized (which, for POD types, technically calls a trivial default constructor). While this does not cause much practical change in behavior, it does simplify the rules somewhat.)

提交回复
热议问题