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 @@
value_initialized
provides
a solution with consistent syntax for value initialization of scalar,
-union and class types. value_initialized
offers a workaround to various
+compiler issues regarding value-initialization.
+
++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; ++ + +
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.@@ -87,14 +156,11 @@ the object shall be default-initialized (but see below). However, if a decla
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 ()
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
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.
+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.
+
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
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 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