请看我的代码。我有一个基类“System”和一个派生类“AdvancedSystem”。当访问基类引用时,输出是未定义的和随机的,我不知道为什么。如果派生类给了我预期的输出。有什么想法吗?
#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
}
字符串
1条答案
按热度按时间dfty9e191#
使用引用作为类成员通常是糟糕设计的标志。在你的情况下,这更糟糕,因为你创建了自引用对象。在这种情况下,你不能依赖rule 0,而是rule 3或rule 5。
在你的vector上的每个
emplace_back
,vector被重新分配,值从旧的分配移动到新的分配。因为你遵循规则0,复制/移动是由自动生成的default
代码处理的;因此system
引用被逐位复制并且由于原始自引用对象被析构,你最终会得到一个dangling reference,它无处可去(随机内存位置)。这是UB的一个通用情况。你可以通过vector::reserve
方法预分配向量来推迟灾难,但这只是隐藏了实际问题,为灾难赢得了时间。最终的解决方案是修改你的设计,以防止在任何情况下出现悬空引用问题。你需要为你的类正确定义复制或移动构造函数。这就是为什么我建议你遵循第1段中的建议。