我有以下两个类:
struct A {
A() : state(0) { }
A(int state_arg)
: state{ state_arg } { }
int state;
};
struct B {
B(int state_arg, const int& ref)
: state{ state_arg }, ref{ ref } { }
int state;
const int& ref;
};
我假装第二个中的字段 ref
是对另一个位置中的整数的引用,也许(但不是必需的)字段 state
的某些实例输入 B
。
现在我想对这些类型执行一些操作,事实上,我使用了 boost::variant 库。
using my_type = boost::variant<A, B>;
现在,当我使用 my_type
的变量时,一切都按预期工作。例如:
int main() {
my_type a(A(45));
my_type b(B(45, boost::get<A>(a).state));
A& at = boost::get<A>(a);
B& bt = boost::get<B>(b);
if (at.state == bt.ref) {
std::cout << "AS EXPECTED" << std::endl;
}
// that prints "AS EXPECTED"
}
但是当我使用 my_type
的 std::vector
时,事情就出错了!
int main() {
std::vector<my_type> vec;
vec.push_back(A(45));
vec.push_back(B(45, boost::get<A>(vec[0]).state));
A& at = boost::get<A>(vec[0]);
B& bt = boost::get<B>(vec[1]);
if (at.state == bt.ref) {
std::cout << "SHOULD I EXPECTED THIS ?" << std::endl;
}
// the code doesn't print
}
现在,我想知道这里发生了什么,即 在上面的代码中,if 条件评估给出 false 是怎么回事?
如果有可能,我希望收到一些关于如何完成此任务的建议。 提前致谢。
最佳答案
问题是,当您将第二个元素添加到 vector 时,它会重新分配更多内存并将第一个对象移动到新位置,并且您有悬空引用。简单的解决方案是提前在 std::vector
中保留足够的内存以防止重新分配或使用另一个不移动对象的容器。但是你原来的解决方案有一个设计缺陷——它依赖于它所引用的对象应该比它长寿的事实。但是您的逻辑无法保证这一点,因此会导致您在 std::vector
中看到的问题。如果对象 b
以某种方式比对象 a
长寿,那么第一个示例中可能会出现同样的问题。更好的解决方案是使用智能指针,让 B
类型的对象持有指向 A
类型对象的共享指针或弱指针,这取决于您想要拥有的所有权。这样您将在 std::vector
中拥有共享指针并且内存重新分配不会影响您:
struct A {
A() : state(0) { }
A(int state_arg)
: state{ state_arg } { }
int state;
};
typedef std::shared_ptr<A> APtr;
struct B {
B(int state_arg, const APtr& ptr)
: state{ state_arg }, aptr{ ptr } { }
int state;
APtr aptr;
int ref() const { return aptr->state; }
}
typedef std::shared_ptr<B> BPtr;
using my_type = boost::variant<APtr, BPtr>;
关于c++ - 将 std::vector、boost::variant 和类型与引用字段一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26892488/