Are there any differences between the following three structure definitions according to the C++ standard?
struct Foo
{
int a;
};
struct Foo
{
int a{};
};
struct Foo
{
int a{0};
};
The last two are C++11.
Given the first definition, if you create an instance of Foo with automatic storage duration, a will be uninitialized. You can perform aggregate initialization to initialize it.
Foo f{0}; // a is initialized to 0
The second and third definitions of Foo will both initialize the data member a to 0.
In C++11, neither 2 nor 3 are aggregates, but C++14 changes that rule so that they both remain aggregates despite adding the brace-or-equal-initializer.
struct Foo
{
int a;
}bar;
bar.a is uninitialized if not in global scope or not-static.
struct Foo
{
int a{};
}bar;
bar.a is initialized to 0
struct Foo
{
int a{0};
}bar;
bar.a is initialized to 0
So constructs 2 and 3 are same. 1 is different.
For more details, you may want to read Initialization and Class Member Initialization
First one is POD type. Member a is initialized by 0.
Related
I have a struct that contains multiple members.
these members should be constructed using another member.
Is accessing this other member for the initialization of the members valid, or am I invoking UB this way?
struct Data {
int b;
};
struct Bar {
Bar(Data& d): a(d.b){
}
int a;
};
struct Foo {
Data data;
Bar b;
};
int main() {
Foo f {.data = Data(), .b = Bar(f.data)}; // b is constructed using f.data!
}
https://godbolt.org/z/fajPjo6oa
Members are initialized in the order they are declared in the struct/class and you can validly reference other members during initialization, as long as they have already been initialized at that point.
This holds regardless of how initialization is performed.
I'm testing the piece of code below:
#include <iostream>
struct foo
{
foo() {}
int a;
};
struct bar
{
bar();
int b;
};
bar::bar() = default;
int main()
{
foo f{};
bar b{};
std::cout << f.a << '\t' << b.b << std::endl;
}
The output is 0 21946.
Well, it seems that the object f is initialized with Zero initialization but the object b is initialized with default initialization. The default initialization of an int is a random number and that's why I got a 21946.
Why did I get two different kinds of initialization here?
I knew that the variable with static storage duration may be initialized with Zero initialization and it put at the .bss segment, this is a kind of static initialization. But foo f{} is obviously a kind of dynamic initialization. Why is f initialized with Zero initialization, instead of default initialization? Why does the compiler make two different behavior?
From cppreference:
Defaulted default constructor outside of class definition (the class must contain a declaration (1)). Such constructor is treated as user-provided
Therefore, none of the statements are value-initializations.
Both are default initialization because they have user-provided constructors. And the values of non-static data members leaves uninitialized (can contain an arbitrary number, including zero)
To do the value initialization for the defaulted constructor case, use the in-class declaration:
struct bar
{
bar() = default;
int b;
};
Someone gave me (part of) the following code:
struct MyStruct
{
int x = {};
int y = {};
};
I never saw this syntax before, what does initialization with {} mean?
This is default member initializer (since C++11),
Through a default member initializer, which is a brace or equals initializer included in the member declaration and is used if the member is omitted from the member initializer list of a constructor.
The initialization itself is copy-list-initialization (since C++11), as the effect, the data member x and y would be value-initialized (and zero-initialized as built-in type) to 0.
Since the C++11 standard there are two ways to initialize member variables:
Using the constructor initialization list as "usual":
struct Foo
{
int x;
Foo()
: x(0)
{
}
};
Use the new inline initialization where members are getting their "default" values using normal initialization syntax:
struct Foo
{
int x = 0;
};
Both these ways are for many values and types equivalent.
I run across a weird concept named "member initializer".
Here says:
C++11 added member initializers, expressions to be applied to members
at class scope if a constructor did not initialize the member itself.
What is its definition?
Are there some examples to illustrate its usage?
It probably refers to in-class member initializers. This allows you to initialize non-static data members at the point of declaration:
struct Foo
{
explicit Foo(int i) : i(i) {} // x is initialized to 3.1416
int i = 42;
double x = 3.1416;
};
More on that in Bjarne Stroustrup's C++11 FAQ.
You can now add initializers in the class which are shared for the constructors:
class A
{
int i = 42;
int j = 1764;
public:
A() {} // i will be 42, j will be 1764
A( int i ) : i(i) {} // j will be 1764
};
It avoids having to repeat initializers in the constructor which, for large classes, can be a real win.
C++11 allows non-static member initialization like this:
class C
{
int a = 2; /* This was not possible in pre-C++11 */
int b;
public:
C(): b(5){}
};
Member initializers is referring to the extension of what initializers can be set up in the class definition. For example, you can use
struct foo
{
std::string bar = "hello";
std::string baz{"world"};
foo() {} // sets bar to "hello" and baz to "world"
foo(std::string const& b): bar(b) {} // sets bar to b and baz to "world"
};
to have bar initialized to hello if the member initializer list doesn't give another value. Note that member initializers are not restricted to build-in types. You can also use uniform initialization syntax in the member initializer list.
From here:-
Non-static Data Member Initializers are a rather straightforward new
feature. In fact the GCC Bugzilla reveals novice C++ users often tried
to use it in C++98, when the syntax was illegal! It must be said that
the same feature is also available in Java, so adding it to C++ makes
life easier for people using both languages.
struct A
{
int m;
A() : m(7) { }
};
struct B
{
int m = 7; // non-static data member initializer
};
thus the code:
A a;
B b;
std::cout << a.m << '\n';
std::cout << b.m << std::endl;
I'm not sure how to use array variables with objects. How do you initialize an array when an object is created. An array that is a data member of an object.
I'm hoping to use an initialization list.
If your compiler supports it, you can do it like this:
struct Foo
{
int n[5];
Foo() :n{1,2,3,4,5} {}
};
Soon enough, that will be standard. GCC supports it now, I'm not sure what other compilers do.
An array member variable can only be default-initialized, you cannot provide explicit initialization values.
struct Foo {
Foo() : bar() {} // Default-initialize bar, for int this means initialize with 0
int bar[10];
};
If you want anything else, you'll have to assign in the constructor body.
struct Foo {
Foo() : bar() {
bar[3] = 1;
}
int bar[10];
};