Value-Initializing an Automatic Object

Value-initializing an automatic object?

The following uses copy-initialization, which is 'probably fine' 95% of the time in C++03:

T var = T();

But for generic (C++03) code, you should always prefer direct-initialization to account for that other 5%:

T var((T())); // extra parentheses avoid the most vexing parse – the extra parentheses
// force the contents to be evaluated as an expression, thus implicitly
// *not* as a declaration.

Or better yet, use the Boost.Utility.ValueInit library, which packages up the ideal behavior for you along with workarounds for various compiler deficiencies (sadly, more than one might think):

boost::value_initialized<T> var;

For C++11, one can use list-initialization syntax to achieve direct value-initialization in a significantly less noisy/ugly manner:

T var{}; // unambiguously value-initialization†

(N.b. technically this will invoke std::initializer_list<> constructors instead of performing value-initialization for certain pathological types. Presumably the net result should be the same.)

value initialization for automatic variables

The term value-initialization is defined in 8.5 [dcl.init] paragraph 16, 4th bullet:

If the initializer is (), the object is value-initialized.

That is, value-initialization of an automatic variable would look like this:

int i();

However, this is a declaration of a function called i returning an int. Thus, it is impossible to value-initialize an automatic. In your example, the temporary is value-initialized and the automatic variable is copy-initialized. You can verify that this indeed requires the copy constructor to be accessible using a test class which doesn't have an accessible copy constructor:

class noncopyable {
noncopyable(noncopyable const&);
public:
noncopyable();
};

int main() {
noncopyable i = noncopyable(); // ERROR: not copyable
}

SINCE C++11: int i{}; does the job (see also this).

C++ default initialization and value initialization: which is which, which is called when and how to reliably initialize a template-type member

Not so hard:

A x;
A * p = new A;

These two are default initialization. Since you don't have a user-defined constructor, this just means that all members are default-initialized. Default-initializing a fundamental type like int means "no initialization".

Next:

A * p = new A();

This is value initialization. (I don't think there exists an automatic version of this in C++98/03, though in C++11 you can say A x{};, and this brace-initialization becomes value-initialization. Moreover, A x = A(); is close enough practically despite being copy-initialization, or A x((A())) despite being direct-initialization.)

Again, in your case this just means that all members are value-initialized. Value initialization for fundamental types means zero-initialization, which in turn means that the variables are initialized to zero (which all fundamental types have).

For objects of class type, both default- and value-initialization invoke the default constructor. What happens then depends on the constructor's initializer list, and the game continues recursively for member variables.

C++: Are local automatic variables initialized or not? Stroustrup example

It's easy. You can leave the built-in type variables uninitialized or you can ask the compiler to zero-initialize them.

S s1;   // string is default initialized, int is left uninitialized
S s2{}; // All fields are initialized.

Notice the {}. That (in this case) asks the compiler to initialize all fields.

the difference of automatic and dynamic variables rules in zero initialization

obj *o2 = new obj(); is value initialization meaning the object will be zero initialized and hence the data member v will be initialized to 0.

This can be seen from value initialization:

This is the initialization performed when an object is constructed with an empty initializer.

new T ()  (2)     

2,6) when an object with dynamic storage duration is created by a new-expression with the initializer consisting of an empty pair of parentheses or braces (since C++11);


On the other hand,

int *v2 = new int; //this uses default initialization
std::cout << *v2 << std::endl; //this is undefined behavior

the above leads to undefined behavior because you're dereferencing v2 and the allocated int object has is uninitialized and so has indeterminate value.

Undefined behavior means anything can happen. But never rely(or make conclusions based) on the output of a program that has UB. The program may just crash.

This can be seen from default initialization:

This is the initialization performed when an object is constructed with no initializer.

new T     (2)     

when an object with dynamic storage duration is created by a new-expression with no initializer;

The effects of default initialization are:

  • otherwise, no initialization is performed: the objects with automatic storage duration (and their subobjects) contain indeterminate values.

What is the best way to give a C# auto-property an initial value?

In C# 5 and earlier, to give auto implemented properties an initial value, you have to do it in a constructor.

Since C# 6.0, you can specify initial value in-line. The syntax is:

public int X { get; set; } = x; // C# 6 or higher

DefaultValueAttribute is intended to be used by the VS designer (or any other consumer) to specify a default value, not an initial value. (Even if in designed object, initial value is the default value).

At compile time DefaultValueAttribute will not impact the generated IL and it will not be read to initialize the property to that value (see DefaultValue attribute is not working with my Auto Property).

Example of attributes that impact the IL are ThreadStaticAttribute, CallerMemberNameAttribute, ...

Storage Duration and Member Initialization of a Struct in C++

So does a1 have Static Storage Duration and does a2 have Automatic Storage Duration?

The definition of Struct A is at global namespace ...

This is irrelevant.

... is at global namespace, as well as a1 declaration

a1 has static storage duration and it is zero-initialized.

while a2 declaration is at block scope

a2 is a non-static block local variable. It has automatic storage duration and it is default initialized. It has an indeterminate value.



What is the Storage Duration of Struct A?

Types do not have storage duration. Objects do.

... And that of objects a1 and a2?

See above.

.. And that of variables a1.x and a2.x?

Subobjects, including non static data members, inherit the lifetime of their superobject.

... Shoud a1.x and a2.x be zero-initialized? Or are they indeterminate values?

a1 is zero initialized. This includes its subobjects. a2 is not. This includes its subobjects.

Do the same rules apply to class and union?

Same set of rules apply to objects of union and non-union classes as well as non class types when it comes to storage classes. There are differences in what default initialization means for different types.

Does it make any difference the code in // Some Other Code? For example, if a constructor of class T "has non-static members with default initializers" then the default constructor can not be trivial (i.e. perform no action).

A non-trivial default constructor generated by the compiler default initializes the members that have no default initializers.



Related Topics



Leave a reply



Submit