【问题标题】:Initializing vector with reference_wrapper's locally在本地使用 reference_wrapper 初始化向量
【发布时间】:2019-09-09 13:03:33
【问题描述】:

我有许多我想从标准容器中使用的继承相关类型(std::reference_wrapper 是此类容器的正确值类型,AFAIU)。但是,我不明白,当插入到映射中的引用值不是全局变量时,如何初始化这样的容器。例如:

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

struct I
{
    virtual void print() = 0;
};

struct S1: public I
{
    void print() override
    {
        cout << "S1 " << i << endl;
    }
    int i{};
};

struct S2: public I
{
    void print() override
    {
        cout << "S2 " << f << endl;
    }
    float f{};
};

std::vector<reference_wrapper<I>> v;

void init()
{
    S1 x{};
    S2 y{};
    v.emplace_back(x);
    v.emplace_back(y);
}

int main()
{
    init();
    v[1].get().print();
    return 0;
}

这可以编译,但我在运行时遇到了一些内存损坏。初始化std::reference_wrappers的容器的正确方法是什么?

【问题讨论】:

  • 如果您需要v 拥有您存储的实例,您需要它是std::vector&lt;std::unique_ptr&lt;I&gt;&gt; 并通过std::make_unique&lt;I&gt;() 使用动态分配。

标签: c++ polymorphism containers reference-wrapper


【解决方案1】:

您不能引用函数本地对象。一旦函数退出,这些本地对象就会被销毁,并且向量中会留下悬空引用。解决此问题的方法是切换到使用 std::unique_ptr&lt;I&gt;std::make_unique 动态分配要存储在向量中的对象。 std::unique_ptr 将管理内存,一旦向量被销毁,它将销毁向量中的std::unique_ptr,它们将依次删除为保存对象而获取的内存。那会给你

#include <iostream>
#include <vector>
#include <functional>
#include <memory>

using namespace std;

struct I
{
    virtual void print() = 0;
};

struct S1: public I
{
    void print() override
    {
        cout << "S1 " << i << endl;
    }
    int i{};
};

struct S2: public I
{
    void print() override
    {
        cout << "S2 " << f << endl;
    }
    float f{};
};

std::vector<unique_ptr<I>> v;

void init()
{
    v.emplace_back(std::make_unique<S1>()); // creates a defaulted S1 in the unique_ptr
    v.emplace_back(std::make_unique<S2>()); // creates a defaulted S2 in the unique_ptr
}

int main()
{
    init();
    v[1]->print(); // or (*v[1]).print()
    return 0;
}

【讨论】:

    【解决方案2】:

    您面临的问题是您的对象S1 xS2 y 在您的init 函数结束时被销毁。因此,在init() 的末尾,您的向量v 包含对任何内容的引用。因此,当尝试调用print() 时,您会得到segmentation fault

    以类似的方式,考虑以下代码:

    int& get_i()
    {
        int i = 1;
        return i;
    }
    
    int main()
    {
        std::cout << get_i() << std::endl; // segmentation fault
        return 0;
    }
    

    这也会产生一个segmentation fault,因为get_i() 返回一个对局部变量的引用(如果get_i(),它会在最后被销毁)。

    您可以改用 std::unique_ptr,如其中一个 cmets 中所述。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-05
      • 2011-05-18
      • 1970-01-01
      • 2012-08-03
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      相关资源
      最近更新 更多