Please see my code. I have a base class "System" and a derived class "AdvancedSystem". When accessing the base class reference the output is undefined and random, and i have no idea why. Accessing the derived class gives me expected output. Any ideas?
#include <iostream>
#include <vector>
class System {
public:
System() :
someValue(12345)
{}
int someValue;
};
class AdvancedSystem : public System {
public:
AdvancedSystem()
{}
};
class Strategies {
public:
Strategies(System& system) :
system(system)
{}
System& system;
};
class Test {
public:
Test() :
system(),
strategies(system)
{}
AdvancedSystem system;
Strategies strategies;
};
class Tests {
public:
void createTests() {
for (int i = 0; i < 18; ++i) {
values.emplace_back();
}
}
std::vector<Test> values;
};
int main() {
Tests tests;
tests.createTests();
std::cout << tests.values[0].system.someValue << "\n"; // outputs expected value of 12345
std::cout << tests.values[0].strategies.system.someValue << "\n"; // outputs random number
}
Using references as class members is usually a sign of bad design. In your case it's even worse because you creat self refenced objects. In such senarios you mustn't rely on rule 0, but rather rule 3 or rule 5.
Upon each
emplace_backon your vector, the vector gets reallocated and values are moved from old allocation to new allocation. Because you follow rule 0, copy/move is handled by auto generateddefaultcode; therefore thesystemreference is bitwise copied and since the original self-referenced object is destructed, you end up with a dangling reference refering to nowhere(random memory location). This is a versatile case of UB. You can postpone the disaster by preallocating the vector viavector::reservemethod, but that only hides the actual problem and buys time for catastrophe.The ultimate solution is to revise your design to prevent dangling reference problem under any circumstances. You need define either copy or move constructor properly for your class. That's why I refer you to follow the recommendation in the 1st paragraph.