If an initializer is specified for an object, that initializer determines the initial value of an object.
An initializer can use one of four syntactic styles:
X a1 {v};
X a2 = {v};
X a3 = v;
X a4(v);
Of these, only the first can be used in every context, and I strongly recommend its use. It is clearer
and less error-prone than the alternatives. However, the first form (used for a1 ) is new in C++11, so
the other three forms are what you find in older code. The two forms using = are what you use in
C. Old habits die hard, so I sometimes (inconsistently) use = when initializing a simple variable
with a simple value. For example:
int x1 = 0;
char c1 = 'z';
However, anything much more complicated than that is better done using {} . Initialization using {} ,
list initialization, does not allow narrowing (§iso.8.5.4). That is:
• An integer cannot be converted to another integer that cannot hold its value. For example,
char to int is allowed, but not int to char .
• A floating-point value cannot be converted to another floating-point type that cannot hold its
value. For example, float to double is allowed, but not double to float .
• A floating-point value cannot be converted to an integer type.
• An integer value cannot be converted to a floating-point type.
For example:
void f(double val, int val2)
{
int x2 = val;
// if val==7.9, x2 becomes 7
char c2 = val2;
// if val2==1025, c2 becomes 1160
Types and Declarations
Chapter 6
int x3 {val};
char c3 {val2}; // error : possible truncation
// error : possible narrowing
char c4 {24};
char c5 {264}; // OK: 24 can be represented exactly as a char
// error (assuming 8-bit chars): 264 cannot be represented as a char
int x4 {2.0}; // error : no double to int value conversion
// ...
}
See §10.5 for the conversion rules for built-in types.
There is no advantage to using {} initialization, and one trap, when using auto to get the type
determined by the initializer. The trap is that if the initializer is a {} -list, we may not want its type
deduced (§6.3.6.2). For example:
auto z1 {99};
auto z2 = 99;
// z1 is an initializer_list<int>
// z2 is an int
So prefer = when using auto .
It is possible to define a class so that an object can be initialized by a list of values and alterna-
tively be constructed given a couple of arguments that are not simply values to be stored. The clas-
sical example is a vector of integers:
vector<int> v1 {99};
vector<int> v2(99);
// v1 is a vector of 1 element with the value 99
// v2 is a vector of 99 elements each with the default value 0
I use the explicit invocation of a constructor, (99) , to get the second meaning. Most types do not
offer such confusing alternatives – even most vector s do not; for example:
vector<string> v1{"hello!"};
vector<string> v2("hello!");
// v1 is a vector of 1 element with the value "hello!"
// error : no vector constructor takes a string literal
So, prefer {} initialization over alternatives unless you have a strong reason not to.
The empty initializer list, {} , is used to indicate that a default value is desired. For example:
int x4 {};
double d4 {};
char∗ p {};
vector<int> v4{};
string s4 {};
// x4 becomes 0
// d4 becomes 0.0
// p becomes nullptr
// v4 becomes the empty vector
// s4 becomes ""
list Initialization using {}
最新推荐文章于 2021-06-14 10:55:40 发布