c++ - 将 std::vector、boost::variant 和类型与引用字段一起使用

标签 c++ boost std stdvector boost-variant

我有以下两个类:

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_typestd::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/

相关文章:

c++ - 声明静态可变值的正确方法是什么

c++ - 使用 boost 反序列化时输入流错误

c++ - boost::asio::io_service 的 concurrency_hint 是什么意思?

c++ - 使用值对 std::map 进行排序

c++ - 如何在 C++0x 中组合哈希值?

c++ - 无法在 OpenCV 中运行 SFM 模块的程序

c++ - 我可以简单地将 dll 库放到 Windows 文件夹中吗?

c++ - 什么是用于索引访问的良好未定义大小数据结构?

c++ - 使用 std::make_shared 抽象类实例化时出错

c++ - 无法链接到 Windows 7 上的 Visual Studio 2013 中的 boost 1.60 线程库