传递unique_ptr< T>的C ++向量没有通过所有权 [英] Pass C++ vector of unique_ptr<T> without passing ownership

查看:47
本文介绍了传递unique_ptr< T>的C ++向量没有通过所有权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个外部类,其中包含一个 Inner 成员和 owns 一个unique_ptr元素的向量:

I have a class Outer which contains an Inner member and owns a vector of unique_ptr elements:

using Elements = std::vector<std::unique_ptr<Element>>;

class Outer
{
    void call()
    {
        _inner.aMethod(_vec);
    }

    Inner _inner;
    Elements _vec;   // This should remain the owner of each Element
};

Inner 接收unique_ptr元素的向量,并将所有权转移给它自己的向量类成员:

Inner receives the vector of unique_ptr elements and it transfers ownership to it's own vector class member:

class Inner
{
    public:
    Inner() = default;
    ~Inner() = default;

    void aMethod(Elements& vec)
    {
        _vec = std::move(vec);
    }

    private:

    Elements _vec;  // This is a vector of unique_ptr but I don't want this class to own the memory
};

我愚蠢地使用了 std :: move(),因为否则编译器会抱怨我试图在每个矢量元素上调用一个已删除的函数(可能是复制构造函数).

I stupidly used std::move() because otherwise the compiler complained I was trying to call a deleted function (probably the copy constructor) on each vector element.

我有一个非法的内存访问权限,我相信是因为两个类都认为它们拥有向量元素,并且一个试图删除已经删除的 Element .

I have an illegal memory access and I believe it is because both classes think they own the vector elements and one has tried to delete an already-deleted Element.

我如何让外部拥有内存,然后将元素传递给 Inner 来使用(不获取所有权)?

How do I have Outer owning the memory and just pass the elements to Inner to use (not take ownership)?

推荐答案

您不能有两个 std :: unique_ptr 指向同一对象. unique_ptr 表示 unique 所有权.

You cannot have two std::unique_ptrs pointing to the same object. unique_ptr implies unique ownership.

如果您需要共享所有权,请改用 std :: shared_ptr s.在您的示例中,它应该是直接替换,只需更改 using 声明:

If you need ownership to be shared, use std::shared_ptrs instead. In your example, it should be a drop-in replacement, just change the using declaration:

using Elements = std::vector<std::shared_ptr<Element>>;


如果您不希望 Inner 对象拥有其 _vec 成员指向的对象,则它应该是原始指针的向量:


If you don't want Inner objects to own the objects pointed to by its _vec member, then it should be a vector of raw pointers:

class Outer
{
    void call()
    {
        std::vector<Element*> observer;
        std::transform(_vec.begin(), _vec.end(), std::back_inserter(observer),
                       [](std::unique_ptr<Element>& el) { return el.get(); });
        _inner.aMethod(observer);
    }

    //...
};

class Inner
{
    // ...

    void aMethod(std::vector<Element*> vec)
    {
        _vec = std::move(vec);
    }

private:
    std::vector<Element*> _vec;
};

当然,这样做意味着如果 Out 释放了任何 Element ,则冒着使 _vec 元素悬空的风险.拥有它,而无需更新指向它们的任何 Inner 对象.您可以通过存储指向 Outer 对象的指针而不是直接存储指向 Element s的指针来部分缓解这种风险:

Of course, doing this would mean that you run the risk of leaving _vec's elements dangling if Outer frees any of the Elements it owns without updating any Inner objects that are pointing to them. You could partially mitigate that risk by storing a pointer to the Outer object instead of storing pointers directly to the Elements:

class Outer
{
    void call()
    {
        _inner.aMethod(this);
    }

    //...
};

class Inner
{
    // ...

    void aMethod(Outer* outer)
    {
        outer_ = outer;
    }

private:
    Outer* outer_;
};

然后,

Inner 只能通过 Outer 对象访问其 Element (您可以将 Inner 设置为<外部的code> friend (如有必要).仍然有可能使 Inner 对象超过其指向的 Outer 对象,但是确实降低了风险.

Inner would then only access its Elements via the Outer object (you could make Inner a friend of Outer if necessary). This still leaves the possibility that an Inner object could outlive the Outer object it points to, but it does reduce the risk somewhat.

这篇关于传递unique_ptr&lt; T&gt;的C ++向量没有通过所有权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆