I've recently come across this:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm> //sort function
#include <functional> //functions utilities
#include <random> //random numbers generation
using namespace std;
default_random_engine generator;
uniform_int_distribution<int> distribution(0,9999);
auto randomer = bind(distribution, generator);
struct Test_struct {
string ord_as_string;
int ord;
Test_struct() :
ord(randomer()),
ord_as_string(to_string(ord))
{}
};
int main() {
vector<Test_struct> my_vector;
for(int i = 0; i < 100; ++i) my_vector.push_back(Test_struct());
for(auto& e: my_vector)
cout << e.ord_as_string << " -> " << e.ord << endl;
}
Which prints the following sequence:
142 -> 0
0 -> 1315
1315 -> 7556
7556 -> 4586
4586 -> 5327
5327 -> 2189
2189 -> 470
470 -> 6788
6788 -> 6792
...
It doesn't make sense since the struct int
and string
attributes should refer to the same logical number.
So I just changed the declaration to:
struct Test_struct {
int ord;
string ord_as_string;
Test_struct() :
ord(randomer()),
ord_as_string(to_string(ord))
{}
};
I thought that it has something to deal with the order of declaration of the struct attributes and it worked:
0 -> 0
1315 -> 1315
7556 -> 7556
4586 -> 4586
5327 -> 5327
2189 -> 2189
470 -> 470
6788 -> 6788
...
So, can someone explain to me why does the reference to ord
is kept in the following structs initializations when it is declared after the other attribute but initialized before?
Edit: Ok, members are initialized in the declaration order as said in the comments, then, why was it designed like that? It makes no sense for me.
You are running into undefined behavior. The order of initialization of the members must match the order of declaration.
Since it does not, the behavior you are observing stems from the ord
member being uninitialized and coincidentally reusing the same location in memory on every iteration of the loop. This location happens to hold the value you assigned in the iteration before.
You can read up here what the order of initialization is, and why it is that way. To summarize both the link and comments: the destructor has to destroy objects in the reverse order of initialization, and since there can be multiple constructors, there has to be a single source of truth, which is the order of declaration in the class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With