#include <iostream>
class MyClass
{
public:
MyClass() :
mFirst()
{
}
int mFirst;
int mSecond;
};
int main()
{
MyClass mc;
std::cout << "mc.mFirst: " << mc.mFirst << std::endl;
std::cout << "mc.mSecond: " << mc.mSecond << std::endl;
int a;
std::cout << "a: " << a << std::endl;
return 0;
}
What is the expected output of this program?
I would think only MyClass.mFirst will be initialized to zero. However GCC initializes them all to zero, even with optimizations enabled:
$ g++ -o test -O3 main.cpp
$ ./test
mc.mFirst: 0
mc.mSecond: 0
a: 0
I'd like to know:
How is each value initialized according to the C++ standard?
Why does GCC initialize them all to zero?
Update
According to Erik the values are zero because my stack happens to contain zeroes. I tried forcing the stack to be non-zero using this construct:
int main()
{
// Fill the stack with non-zeroes
{
int a[100];
memset(a, !0, sizeof(a));
}
MyClass mc;
std::cout << "mc.mFirst: " << mc.mFirst << std::endl;
std::cout << "mc.mSecond: " << mc.mSecond << std::endl;
int a;
std::cout << "a: " << a << std::endl;
return 0;
}
However, the output stays the same:
mc.mFirst: 0
mc.mSecond: 0
a: 0
Can anyone explain why?
Update 2
Ok I figured it out. GCC was probably optimizing away unused variables.
This application shows the expected behavior:
#include <iostream>
struct MyClass
{
MyClass() : mFirst() { }
MyClass(int inFirst, int inSecond) : mFirst(inFirst), mSecond(inSecond) { }
int mFirst;
int mSecond;
};
int main()
{
// Fill the stack with non-zeroes
// Use volatile to prevent GCC optimizations.
{
volatile MyClass mc(1, 2);
volatile int a = 3;
}
{
volatile MyClass mc;
volatile int a;
std::cout << "mc.mFirst: " << mc.mFirst << std::endl;
std::cout << "mc.mSecond: " << mc.mSecond << std::endl;
std::cout << "a: " << a << std::endl;
}
return 0;
}
Output:
$ g++ -o test main.cpp
$ ./test
mc.mFirst: 0
mc.mSecond: 2
a: 3
They're (EDIT: With "They" i refer to mSecond and a which are not explicitly initialized) not initialized. Your stack happens to contain 0's so that's the values you get.
8.5/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
value; if the object or any of its
subobjects are of const-qualified
type, the program is ill-formed.
They are classified as 'undefined' meaning whatever the compiler decides or whatever was in memory at that location at the time of creation. Basically, leaving them uninitialised is leaving it up to chance and you should initialise them. The only reason for not initialising members of a struct that I can think of is if you have a very, very large array and don't want to be calling a constructor many times.
Related
This question already has answers here:
What's the point of g++ -Wreorder?
(5 answers)
Closed 2 years ago.
I am reading into Scott Meyers book Effective c++. For constructors he recommends initialization of object data in a specific order.
Base class before derived class
Within a class data members initialized in the order which the are declared.
Appearantly not following these rules can lead to obscure behavioral bugs ... However he does'nt give any examples or go into details.
Can you give an example of what kind of bugs can occur?
For example,
struct S
{
int a;
int b;
S() : b(42), a(b + 1) {}
};
leads to undefined behavior:
As contrary as we might expect from constructor,
a is initialized before b (according to member order).
It can confusing to have the wrong order:
struct foo {
int a;
int b;
foo(int x) : b(++x),a(++x) {
std::cout << "a = " << a <<'\n';
std::cout << "b = " << b <<'\n';
}
};
Constructing a foo(1) prints:
a = 1
b = 2
Not a = 2, b = 1 as one might expect from the order of the initializer list. Real problems can occur if initialization of one member depends on another member. This is correct (but not nice):
struct bar {
int a;
int b;
bar() : b(a),a(1){
std::cout << "a = " << a <<'\n';
std::cout << "b = " << b <<'\n';
}
};
Prints:
a = 1
b = 1
And this invokes undefined behavior:
struct broken {
int a;
int b;
broken() : b(1),a(b){
std::cout << "a = " << a <<'\n';
std::cout << "b = " << b <<'\n';
}
};
Can you give an example of what kind of bugs can occur?
class foo
{
int *ptr;
int size;
public:
foo() : size(10), ptr(new int[size]) {}
};
int main()
{
foo f;
}
See the warnings here.
The size is initialized after the ptr is initialized, thus size is actually some random value when new is issued to allocate dynamically.
This question already has answers here:
Initialization Order of Class Data Members
(2 answers)
Closed 3 years ago.
I'm trying to understand member class initialization order but there is one thing that confusing me.
#include <iostream>
class Foo {
int y{7};
public:
Foo()
{
std::cout << "Foo Constructor";
}
explicit Foo(int yy) : y(yy)
{
std::cout << "Foo " << y << std::endl;
}
int gety()
{
std::cout << "Foo::gety() returning ";
return y;
}
};
class Bar {
int x;
public:
Bar()
{
std::cout << "Bar constructor" << std::endl;
}
explicit Bar(int xx) : x(xx)
{
std::cout << "Bar "<< x << std::endl;
}
int getx()
{
std::cout << "Bar::getx() returning ";
return x;
}
};
class Class {
Bar bar;
Foo foo;
public:
Class() : bar(foo.gety()), foo(5)
{
std::cout << "Class()\n";
}
void printxy()
{
std::cout << "Bar.x = " << bar.getx() << " \n" << "Foo.y = " << foo.gety() << std::endl;
}
};
int main(void)
{
Class k;
k.printxy();
return 0;
}
I'm compiling this code with gcc --std=c++11 -Wuninitialized -Wall -pedantic
In Class object there is two members of class Foo and Bar. In initialization list I'm constructing firs bar object by using constructor that takes int as argument. But as i understand foo is not constructed yet because it's second in order on initialization list. So how i don't get any errors when using foo.gety() before it's constructed?
I think C++ is guarantee that any used object is constructed. So when Foo object is constructed? Or this is undefined behavior?
This is link for coliru example: Link
Member variables are initialized in the order they are defined in the class. In your case bar will be initialized before foo (even if you change the order in the constructor initializer list).
What you're doing, using the uninitialized foo object, will lead to undefined behavior. There's no guarantee that a compiler will be able to catch it or even report it.
I have edited the question after changing the c++17 to 11
#include <cstdio>
#include <iostream>
#include <initializer_list>
using namespace std;
class A
{
public:
static int s;
int t = s;
A(){
cout << "constructed" << t<< endl;
s++;
}
A (A&& a) {
cout << "in move ctor, moving"<< a.t << " creating" << s << endl;
s++;
}
~A() {
cout << "deleting"<< t << endl;
}
};
A f1 (A a)
{
std::cout << "f1: " << endl;
return a;
}
int A::s = 0;
int main() {
f1(A()) ;
std::cout << "is still alive!" << endl;
}
which compiles with g++ -std=c++11 -fno-elide-constructors -Wall -pedantic -pthread main.cpp && ./a.out
The output is:
constructed0
in move ctor, moving0 creating1
f1:
in move ctor, moving1 creating2
deleting2
deleting1
deleting0
is still alive!
And i can't understand why.
If f1 receives A by value, and it is being given with a A&& object (from f2), It create a temporary object "a" inside f1 function right?
If so, when exiting the temporary object (here "1") should have been destroyed, no? from what i can tell from the example, the temporary object is being destroyed at the end of the line, with all the other temporary objects, and not inside f1 function
So the question is:
does an object that is being created solely for a function is destroyed inside(at the end) of the function? or it is being destroyed at the end of the line creating it.
Thanks a lot
I am fiddling with a code like following:
union Data {
int i;
double x;
std::string str;
~Data(){}
};
union Data var = {.x = 31293.932};
std::cout << var.x << "\n";
std::cout << var.str << "\n";
std::cout << var.i << "\n";
As far as I know, the union have some 64 bit thing written after I set x member to some floating point number. Then I want to see corresponding string, asuming I treated those bytes as char. But I am getting segmentation fault when I try to print it as string. Why is that? I initialized the union so I assume var.str must be initialized as well.
str is not constructed. if you must use str you must either provide a constructor for it or construct it via placement new. A full example below
#include <iostream>
#include <vector>
using namespace std;
union Data
{
int i;
double x;
std::string str;
Data() {}
Data(std::string st) : str(st) {}
~Data() {}
};
int main()
{
Data var;
var.x = 31293.932;
new (&var.str) std::string("Hello World!");
std::cout << var.x << "\n";
std::cout << var.str << "\n";
std::cout << var.i << "\n";
//destroy it
var.str.std::string::~string();
}
EDIT:
Just to expand my answer a bit...
MSDN seems to have a n00bie friendly explanation about unions than cppreference. So, check: Unions - MSDN and Unions - cppreference
You should be using char to access the bytes in the union. std::string is not a POD type and can't be used in this way.
Try this instead:
union Data {
int i;
double x;
char bytes[sizeof(double)];
~Data(){}
};
union Data var = {.x = 31293.932};
std::cout << var.x << "\n";
std::cout.write(var.bytes, sizeof(var.bytes));
std::cout << "\n" << var.i << "\n";
The full definition of what a POD type is extensive. In very simple terms it is a basic data type without a explicitly-defined copy constructor, destructor, or virtual methods and does not itself contain any such types if it is an aggregate type (like struct, class, and unions).
For example, in this piece of code, if line [a] is commented out, the output is 0.
inh2.cpp
#include<iostream>
using namespace std;
class A {
public:
int x;
A() { x = 10; }
};
class B : public A {
public:
int x; // <--------- [a]
B() { x = 0; }
};
int main() {
A* ab = new B;
cout << ab->x << endl;
}
results from gcc
$ g++ inh2.cpp
$ ./a.out
10
$
I have two questions:
How does ab->x resolve to 10 in the above case? The object is of type class B, and thus should value to 0.
Why does commenting Line [a] change the behaviour of the code? My reasoning is that x would have anyways been inherited, which should result in same behaviour.
My reasoning for Q #1 above:
ab points to the memory location of an object of class B. It is a physical object in the sense that all the variables with their values are assigned memory.
Variable x within this object stores value 0.
When ab->x is done, ab tells us the memory location of the object, and we go look inside it to find that x is 0. So we should print 0.
Where am I wrong here?
Yes, it is of type B, but you are assigning it as a pointer to an A, and therefore it is using the x defined on A (as when we're dealing with a pointer to A, we don't know that B even exists, even though that's what you allocated).
When you comment out the line, during the construction phase, As constructor is called first, then Bs constructor, which sets x (in its base class) to 0. There is only one x at this point, and Bs constructor is called last.
Making a some small modifications:
#include <iostream>
using namespace std;
class A {
public:
int x;
A()
:x(10)
{
std::cout << __FUNCTION__ << std::endl;
std::cout << x << std::endl;
}
virtual ~A() {}
};
class B : public A {
public:
int x; // <--------- [a]
B()
:A()
,x(0)
{
std::cout << __FUNCTION__ << std::endl;
std::cout << x << std::endl;
}
};
int main() {
A* ab = new B;
cout << "ab->x: " << ab->x << endl;
cout << "ab->A::x " << ab->A::x << endl;
B* b = dynamic_cast<B*>(ab);
cout << "b->x: " << b->x << endl;
cout << "b->A::x " << b->A::x << endl;
cout << "b->B::x " << b->B::x << endl;
}
This gives you:
A
10
B
0
ab->x: 10
ab->A::x 10
b->x: 0
b->A::x 10
b->B::x 0
This demonstrates that:
ab->x refers to A::x because ab is of type A* and there is no such thing as a virtual variable. If you want polymorphism, you'll have to write a virtual int get_x() const method.
B::x hides A::x. This is a bad idea and should be avoided. Consider using a more meaningful name for your member variables and establish whether you can reuse the base class's variable before introducing a new one.
Casting to a B* allows you access to B's members as well as A's. This should be self-explanatory.