Is a member initialization list without a value defined? [duplicate] - c++

This question already has an answer here:
Constructor initialization list with empty initialization
(1 answer)
Closed 1 year ago.
Say I have :
class Foo
{
public:
int x;
Foo() : x() {}
}
Would it be UB to read x after the constructor has ran? More specifically, what type of initialization is this, zero, direct or default initialization?
I know if instead we'd have:
Foo() : x(42) {}
x would be direct-initialized to 42 but I'm not so sure for the snippet above and I don't want to get bit by the UB wolf if this turns out to be default-initialized.

what type of initialization is this
x() performs value-initialization:
when a non-static data member or a base class is initialized using a member initializer with an empty pair of parentheses or braces (since C++11);
As non-class type int, x is zero-initialized as 0 at last.
otherwise, the object is zero-initialized.

Related

initializing struct with {0}

I'm debugging some code that essentially is identical to this:
struct Foo { int a; int b; };
struct Bar { Bar() {} Foo foo{0}; };
When I make an instance of Bar, it seems like both a and b are initialized to zero. Is this guaranteed? Where can I find that in the spec?
According to cppreference.com
If the number of initializer clauses is less than the number of members [and bases (since C++17)] or initializer list is completely empty, the remaining members [and bases (since C++17)] are initialized [by their default member initializers, if provided in the class definition, and otherwise (since C++14)] by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
Foo has no default member initializers (int b{0};), so b will be initialized by list-initialization with an empty list, which means value-initialization for non-class types: b = int() // = 0.

Why doesn't VS2013 zero-initialize this struct? [duplicate]

This question already has answers here:
Value initialization and Non POD types
(2 answers)
Closed 8 years ago.
Using Microsoft Visual Studio Ultimate 2013 update 4 and the following code:
#include <iostream>
auto main() -> int {
struct Base { int a; };
struct Derived : Base { int b; };
auto foo = Derived();
std::cout << foo.a << " " << foo.b;
}
I get this output:
-858993460 -858993460
But I expected:
0 0
Why is foo not zero-initialized?
Should be initialized to zero, looks like MSVC bug.
Since actually your code is like this
Derived foo{Derived()};
then copy/move constructor will be called on temporary object initialized with ().
n3376 8.5/10
An object whose initializer is an empty set of parentheses, i.e., (),
shall be value-initialized.
n3376 8.5/7
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) non-union class type without a
user-provided or deleted default construc- tor, then the object is
zero-initialized and, if T has a non-trivial default constructor,
default-initialized;
n3376 8.5/5
To zero-initialize an object or reference of type T means:
if T is a (possibly cv-qualified) non-union class type, each
non-static data member and each base-class subobject is
zero-initialized and padding is initialized to zero bits;
Your structs have no constructors, so default one are created.
Default constructor of a struct will call default constructor for each of memebers.
Default constructor of int doesn't initialize it. So int memeber will contain random data.
Add constructors to your structs and initialize memebers. Like this:
struct Base
{
Base(): a(0) {}
int a;
};

Use of ":" symbol to define a constructor in C++ [duplicate]

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Why should I prefer to use member initialization lists?
(9 answers)
Closed 8 years ago.
I am moving from structural C to OOP C++ and I frequently found a special use of ":" symbol as an operator when declaring/defining constructors in C++. I roughly understood the use of this style but somebody explain me the exact programming technique with this constructor definition.
e.g.: 1
class time_stamp
{
public:
time_stamp(time &t_time)
: m_time(t_time)
{}
~time_stamp()
{
m_time.update(); // as soon as I'm destroyed, update the time
}
private:
time &m_time;
};
e.g.: 2
class threaded_class
{
public:
threaded_class()
: m_stoprequested(false), m_running(false)
{
pthread_mutex_init(&m_mutex);
}
~threaded_class()
{
pthread_mutex_destroy(&m_mutex);
}
/** Some other member declarations */
}
Please explain me use of ":" in below lines of codes from above 2 examples
time_stamp(time &t_time) : m_time(t_time){} and
threaded_class(): m_stoprequested(false), m_running(false)
{
pthread_mutex_init(&m_mutex);
}
The colon character : is used to denote the constructor member initializer list. This is the place where you can initiailze members of a class or call a base class constructor.
C++ Standard n3337 12.6.2 § 3:
A mem-initializer-list can initialize a base class using any
class-or-decltype that denotes that base class type.
C++ Standard n3337 12.6.2 § 7:
The expression-list or braced-init-list in a mem-initializer is used
to initialize the designated subobject (or, in the case of a
delegating constructor, the complete class object) according to the
initialization rules of 8.5 for direct-initialization.
Example:
class Foo {
int a;
};
If you would like integer a to have determined value after call to constructor is made you have to give a this value in constructor. There are two options:
in constructor body
Foo::Foo() {
a = 70;
}
in it's member initializer list
Foo::Foo() : a( 70) {
}
Initialization via a member initilization list should be preferred
It is always legal, is never less efficient than assignment inside the body of the constructor, and is often more efficient. The very important thing about initialization list is that it allows to direct initialize class member omitting a default construction of a member being subject to such a process.
As Scott Myers pointed out in his "Effective C++", if you fail to specify an initialization argument for class member, it's default constructor will be called. When you later perform an assignment to it inside your class constructor, you will call operator= on member variable. That will total two calls to member functions: one for the default constructor and one more for the assignment. You can omit a first call by specifying an initializer. Also as Scott Myers pointed out in his "Effective C++" : "from a purely pragmatic point of view, there are times when the initialization list must be used. In particular, const and reference members may only be initialized, never assigned".
A trap
(At least) Equally important thing is that members are not initialized in order of their appearance in initialization list but in order of declaration in class. Remember this to avoid errors like
/* trying to allocate very large block of memory
as a result of initializing a vector with
uninitialized integer: std::vector<int> v( N)
*/
class SearchEngine {
std::vector<int> v;
int N;
explicit SearchEngine( std::vector<int> const& keys)
: N( keys.size()), v( N), {
C++ Standard n3337 8.5.4 § 1:
List-initialization is initialization of an object or reference from a
braced-init-list. Such an initializer is called an initializer list,
and the comma-separated initializer-clauses of the list are called the
elements of the initializer list. An initializer list may be empty.
List-initialization can occur in direct-initialization or copy-
initialization contexts; list-initialization in a
direct-initialization context is called direct-list-initialization and
list-initialization in a copy-initialization context is called
copy-list-initialization. [ Note: List-initialization can be used — as
the initializer in a variable definition (8.5)
— as the initializer in
a new expression (5.3.4)
— in a return statement (6.6.3)
— as a
function argument (5.2.2)
— as a subscript (5.2.1)
— as an argument to
a constructor invocation (8.5, 5.2.3)
— as an initializer for a
non-static data member (9.2)
— in a mem-initializer (12.6.2)
— on the
right-hand side of an assignment (5.17)
[ Example:
int a = {1};
std::complex z{1,2};
new std::vector{"once",
"upon", "a", "time"}; // 4 string elements
f( {"Nicholas","Annemarie"}
); // pass list of two elements
return { "Norah" }; // return list of
one element
int* e {}; // initialization to zero / null pointer
x =
double{1}; // explicitly construct a double
std::map
anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} };
— end example ] — end note ]
It's for member initialisation. This is the only place you can init members without them being default initialised.
If you do it within curly braces, the default constructor for members has already been invoked and your assigning new value to it. With the colon syntax, you decide how members are initialised (in terms of value fortrivial types and in terms of constructor with non trivial ones).
Initialization list. It is useful when you want to initialize the member objects right after construction. And you have to use it when a member object has a not a default constuctor.
And it's not just another way to initialize members, sometimes you have to use it, and most of the time you should use it to keep the code consistence.
Here is an example for a situation that you have to use it:
struct A
{
const X x; // X has not default constructor
A() : x(some_value) {}
};
Even if a member object has a default constructor, you should initialize it by initialization-list to avoid redundant construction.
struct A
{
string x;
A() : x("Hello") {}
};
In the above case, if you assign "Hello" inside the constructor's body, then you made an unnecessary call to string::string() and then x = "Hello";, which it can be replaced by just one call to string::string("Hello").

Constructor initialization list for POD member types using () [duplicate]

This question already has answers here:
No initializer list vs. initializer list with empty pairs of parentheses
(2 answers)
Closed 9 years ago.
Following is a sample code I cooked up to aid my question:
class test {
public:
test(int x, int y) : _x(x), _y() {}
private:
int _x, _y;
};
For POD (plain data types), does _y() (empty parenthesis) have any effect? If so, what is _y getting initialized to? If no effect, is it inefficient having _y() in the list.
Thank you,
Ahmed.
The member initializer _y() has the effect of value initialization and initializes _y to zero.
Constructor initialization lists perform direct-initialization (C++11 §12.6.2/7):
The expression-list or braced-init-list in a mem-initializer is used to initialize the designated subobject ... according to the initialization rules of 8.5 for direct-initialization.
The initialisation rules state the () will value-initialize an object (§8.5/16):
If the initializer is (), the object is value-initialized.
To value-initialize a POD type is to zero-initialize it, which means to set its value or its subobjects' values to 0 (§8.5/5):
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), [... not a POD]
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object
is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, [... not a POD]
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.
In the case of an array type, it's only a POD type if its elements are POD types, so they end up being zero-initialized.

value initialization for automatic variables [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
non-copyable objects and value initialization: g++ vs msvc
Value-initializing an automatic object?
Consider the following statement:
It's not really possible to value-initialize an automatic object.
Is this statement true? I see no problem in doing this:
int main()
{
int i = int();
}
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).