value initialization for automatic variables [duplicate] - c++

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).

Related

What does 'default-initialization in copy-initialization context' mean in C++?

For example I guess I understand what list-initialization in context of direct-initialization (vs copy-) mean - int x{} vs int x = {} basically.
But on cppreference I found this:
When an object of class type is copy-initialized from an object of the same or derived class type, or default-initialized in a copy-initialization context, the candidate functions are all converting constructors of the class being initialized. The argument list is the expression of the initializer.
I guess I understand why candidates are converting constructors for the first case, but not for the second. I mean, I can't write something like MyClass x = MyClass, and = MyClass() would be a value-initialization, and = MyClass(args...) would be a direct-initilization.
And even if such a construct existed, I don't see why a temporary MyClass object 'construction' should include specifically all converting constructors.
(And x is not something that's talked about here as I see, because it's definitely copy-constructed, not default-constructed.)
So I guess I'm confused with the terms here.
This wording is added in the paper P0398R0, which is intented to describe the following case:
Z c = {};
for non-aggregate Z.
This means, when you initialize an object, it is not default constructed and then copied using assignment operator, but always immediately constructed from the parameters given in the initialization. Therefore it uses only the conversions, when you use the assignment notation.
Example:
Given the class:
class MyClass
{
MyClass();
MyClass(int);
};
The following statement are only calling the MyClass::MyClass(int) and no default constructor.
MyClass obj = 10;
MyClass obj{10};
MyClass obj = {10};

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;
};

discrepancy between clang and g++ in dealing with const objects [duplicate]

This question already has an answer here:
Why does gcc allow a const object without a user-declared default constructor but not clang?
(1 answer)
Closed 8 years ago.
Consider the code:
struct Foo
{
int x = 10;
};
int main()
{
const Foo foo;
}
It compiles under g++ http://coliru.stacked-crooked.com/a/99bd8006e10b47ef, however spits an error under clang++ http://coliru.stacked-crooked.com/a/93f94f7d9625b579 :
error: default initialization of an object of const type
'const Foo' requires a user-provided default constructor
I am not sure who's right here. Why do we need a default ctor since we perform in-class initialization?
An object of class type may only be default-initialized if it has a user-provided default constructor. From [dcl.init]/7:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
Your class Foo doesn't have that; the presence of a brace-or-equals-initializer does not create a user-provided default constructor. Rather, your class has an implicitly defined default constructor, whose action incorporates the initialization as requested by the brace-or-equals-initializer. (Clang is right.)
([dcl.fct.def.default], in particular paragraph 5, relates the definitions of "user-provided", "explicitly defaulted", "implicitly declared" and "defined as deleted". The entire section is worth knowing.)
By the way, it's easy to avoid default-initialization in C++11:
const Foo foo {}; // hunky-dory
clang seems to be right according to 8.5 [dcl.init] paragraph 7 last sentence:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
Clearly, the type doesn't have a user-provided default constructor.

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").

Compiler complaints for const object not initialized [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
uninitialized const
I understand that a const object needs to initialized.
So for the following code,
class sample
{};
int main()
{
const sample obj;
return 0;
}
the compiler will complain because the const object obj is not initialized.
But when i modify the code(show below) with a default constructor, the compiler will not throw any error.
class sample
{
public:
sample() { }
};
int main()
{
const sample obj;
return 0;
}
What is the thing that the newly added default ctor does which satisfies the compiler?
What is the thing that the newly added default ctor does which satisfies the compiler?
Because that is the requirement imposed by the C++ standard when declaring objects with the const qualifer.
Reference:
C++03 8.5 Initializers 8 Declarators
§9:
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value90); if the object or any of its subobjects are of const-qualified type, the program is ill-formed.
You're doing a default initialization of a const-qualified type. The C++ (C++11 draft n3290) standard has this to say about that (§8.5/6 Initializers):
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
Your first sample doesn't conform to this (no user-provided constructor). The second does.