diff --git a/value_init.htm b/value_init.htm index 8ceba8b..7cf9e9b 100644 --- a/value_init.htm +++ b/value_init.htm @@ -17,11 +17,13 @@
Rationale
Introduction
+
Details
@@ -46,22 +48,89 @@ for initialization. Depending on the type, the value of a newly constructed the default constructor), or indeterminate. When writing generic code, this problem must be addressed. value_initialized provides a solution with consistent syntax for value initialization of scalar, -union and class types.
+union and class types. +Moreover, value_initialized offers a workaround to various +compiler issues regarding value-initialization. + +

Introduction

+

+There are various ways to initialize a variable, in C++. The following +declarations all may have a local variable initialized to its default +value: +

+  T1 var1;
+  T2 var2 = 0;
+  T3 var3 = {};
+  T4 var4 = T4();
+
+Unfortunately, whether or not any of those declarations correctly +initialize the variable very much depends on its type. The first +declaration is valid for any +DefaultConstructible type (by definition). +However, it does not always do an initialization! +It correctly initializes the variable when it's an instance of a +class, and the author of the class has provided a proper default +constructor. On the other hand, the value of var1 is indeterminate when +its type is an arithmetic type, like int, float, or char. +An arithmetic variable +is of course initialized properly by the second declaration, T2 +var2 = 0. But this initialization form usually won't work for a +class type (unless the class was especially written to support being +initialized that way). The third form, T3 var3 = {} +initializes an aggregate, typically a "C-style" struct or a "C-style" array. +However, the syntax is not allowed for a class that has an explicitly declared +constructor. (But watch out for an upcoming C++ language change, +by Bjarne Stroustrup et al [3]!) +The fourth form is the most generic form of them, as it +can be used to initialize arithmetic types, class types, aggregates, pointers, and +other types. The declaration, T4 var4 = T4(), should be read +as follows: First a temporary object is created, by T4(). +This object is value-initialized. Next the temporary +object is copied to the named variable, var4. Afterwards, the temporary +is destroyed. While the copying and the destruction are likely to +be optimized away, C++ still requires the type T4 to be +CopyConstructible. +(So T4 needs to be both DefaultConstructible and CopyConstructible.) +A class may not be CopyConstructible, for example because it may have a +private and undefined copy constructor, +or because it may be derived from boost::noncopyable. +Scott Meyers [4] explains why a class would be defined like that. +

+

+There is another, less obvious disadvantage to the fourth form, T4 var4 = T4(): +It suffers from various compiler issues, causing +a variable to be left uninitialized in some compiler specific cases. +

+

+The template value_initialized +offers a generic way to initialize +an object, like T4 var4 = T4(), but without requiring its type +to be CopyConstructible. And it offers a workaround to those compiler issues +regarding value-initialization as well! It allows getting an initialized +variable of any type; it only requires the type to be DefaultConstructible. +A properly value-initialized object of type T is +constructed by the following declaration: +

+  value_initialized<T> var;
+
+

+ +

Details

The C++ standard [1] contains the definitions of zero-initialization and default-initialization. Informally, zero-initialization means that the object is given the initial value 0 (converted to the type) and default-initialization means that - POD [2] types are zero-initialized, while class + POD [2] types are zero-initialized, while non-POD class types are initialized with their corresponding default constructors. A declaration can contain an initializer, which specifies the object's initial value. The initializer can be just '()', which states that -the object shall be default-initialized (but see below). However, if a declaration +the object shall be value-initialized (but see below). However, if a declaration has no initializer and it is of a non-const, non-static - POD type, the initial value is indeterminate:(see §8.5 for the + POD type, the initial value is indeterminate: (see §8.5, [dcl.init], for the accurate definitions).

int x ; // no initializer. x value is indeterminate.
std::string s ; // no initializer, s is default-constructed.

int y = int() ;
// y is initialized using copy-initialization
// but the temporary uses an empty set of parentheses as the initializer,
// so it is default-constructed.
// A default constructed POD type is zero-initialized,
// therefore, y == 0.

void foo ( std::string ) ;
foo ( std::string() ) ;
// the temporary string is default constructed
// as indicated by the initializer ()
@@ -87,14 +156,11 @@ the object shall be default-initialized (but see below). However, if a decla

In order to specify value-initialization of an object we need to use the empty-set initializer: ().

-

(but recall that the current C++ Standard states that '()' invokes default-initialization, -not value-initialization)

-

As before, a declaration with no intializer specifies default-initialization, and a declaration with a non-empty initializer specifies copy (=xxx) or direct (xxx) initialization.

-
template<class T> void eat(T);
int x ; // indeterminate initial value.
std::string s; // default-initialized.
eat ( int() ) ; // value-initialized
eat ( std::string() ) ; // value-initialied
+
template<class T> void eat(T);
int x ; // indeterminate initial value.
std::string s; // default-initialized.
eat ( int() ) ; // value-initialized
eat ( std::string() ) ; // value-initialized

value-initialization syntax

@@ -102,7 +168,7 @@ not value-initialization)

parentheses is not permitted by the syntax of initializers because it is parsed as the declaration of a function taking no arguments:

-
int x() ; // declares function int(*)()
int y ( int() ) ; // decalares function int(*)( int(*)() )
+
int x() ; // declares function int(*)()

Thus, the empty () must be put in some other initialization context.

@@ -124,8 +190,50 @@ data member:

template<class T> 
struct W
{
// value-initialization of 'data' here.
W() : data() {}
T data ;
} ;
W<int> w ;
// w.data is value-initialized for any type.
-

This is the solution supplied by the value_initialized<> template - class.

+

This is the solution as it was supplied by earlier versions of the +value_initialized<T> template + class. Unfortunately this approach suffered from various compiler issues.

+ +

compiler issues

+ +Various compilers haven't yet fully implemented value-initialization. +So when an object should be value-initialized (according to the C++ Standard), +it may in practice still be left uninitialized, because of those +compiler issues! It's hard to make a general statement on what those issues +are like, because they depend on the compiler you are using, its version number, +and the type of object you would like to have value-initialized. +Compilers usually support value-initialization for built-in types properly. +But objects of user-defined types that involve aggregates may in some cases +be partially, or even entirely left uninitialized, when they should be value-initialized. +

+

+We have encountered issues regarding value-initialization on compilers by +Microsoft, Sun, Borland, and GNU. Here is a list of bug reports on those issues: + +
+ +Microsoft Feedback ID 100744 - Value-initialization in new-expression +
Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005-07-28 +
+ +GCC Bug 30111 - Value-initialization of POD base class doesn't initialize members +
Reported by Jonathan Wakely, 2006-12-07 +
+ +GCC Bug 33916 - Default constructor fails to initialize array members +
Reported by Michael Elizabeth Chastain, 2007-10-26 +
+ +Borland Report 51854 - Value-initialization: POD struct should be zero-initialized +
Reported by Niels Dekker (LKEB, Leiden University Medical Center), 2007-11-09 +
+
+

+New versions of value_initialized +(Boost release version 1.35 or higher) +offer a workaround to these issues: value_initialized will now clear +its internal data, prior to constructing the object that it contains. +

Types

@@ -191,23 +299,36 @@ the wrapped object is always performed with the get() idiom:

value_initialized<int> x ;
get(x) = 1 ; // OK

value_initialized<int const> cx ;
get(x) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int> const x_c ;
get(x_c) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int const> const cx_c ;
get(cx_c) = 1 ; // ERROR: Cannot modify a const object

References

- [1] The C++ Standard, ISO/IEC 14882:98
- [2] Plain Old Data + [1] The C++ Standard, Second edition (2003), ISO/IEC 14882:2003
+ [2] POD stands for "Plain Old Data"
+ [3] Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote + various papers, proposing to extend the support for brace-enclosed initializer lists + in the next version of C++. + This would allow a variable var of any DefaultConstructible type + T to be value-initialized by doing T var = {}. + The papers are listed at Bjarne's web page, + My C++ Standards committee papers
+ [4] Scott Meyers, Effective C++, Third Edition, item 6, + Explicitly disallow the use of compiler-generated functions you do not want, + Scott Meyers: Books and CDs +

Acknowledgements

value_initialized was developed by Fernando Cacciola, with help and suggestions from David Abrahams and Darin Adler.
Special thanks to Björn Karlsson who carefully edited and completed this documentation. - + +

value_initialized was reimplemented by Fernando Cacciola and Niels Dekker +for Boost release version 1.35 (2008), offering a workaround to various compiler issues. +

Developed by Fernando Cacciola, the latest version of this file can be found at www.boost.org, and the boost discussion list -at www.yahoogroups.com/list/boost. + href="http://www.boost.org">www.boost.org.


-

Revised 19 September 2002

+

Revised January 2008

-

© Copyright Fernando Cacciola, 2002.

+

© Copyright Fernando Cacciola, 2002, 2008.

Distributed under the Boost Software License, Version 1.0. See www.boost.org/LICENSE_1_0.txt