Non-ownership copies of std::unique_ptr

╄→尐↘猪︶ㄣ 提交于 2021-02-05 08:58:06

问题


There's two containers: owner and non-owner of resource. As I have only 1 owner, I suppose I need unique_ptr.

class OwnershipContainer {
public:
    void add(std::unique_ptr<Obj> obj) {
        objects.push_back(std::move(obj));
    }
    Obj* get(std::size_t i) { return objects[i].get(); }
private:
    std::vector<std::unique_ptr<Obj>> objects;
};

What of kind of pointer i have to use for non-owner container? First thought was raw pointer. But i cannot give guarantee that lifetime of Obj match or exceed lifetime of Non-owner container.

class NonOwnershipContainer {
public:
    void add(Obj *obj) {
        objects.push_back(obj);
    }
    Obj* get(std::size_t i) { return objects[i]; }
private:
    std::vector<Obj*> objects;
};

int main() {
    NonOwnershipContainer nonOwnershipContainer;
    {
        OwnershipContainer ownershipContainer;
        ownershipContainer.add(std::make_unique<Obj>(1));

        nonOwnershipContainer.add(ownershipContainer.get(0));
    }
    auto pobj = nonOwnershipContainer.get(0); // dangling pointer
}

I could use shared_ptr for owner and weak_ptr for non-owner, so I could check if weak_ptr is expired or not. But shared_ptr means that i have shared ownership, that's not true in my case, and I no need reference counter.

EDIT:

I'm not trying to extend lifetime. When owner container is destroyed, I want to avoid dangling pointers. As I wrote above, I could use shared_ptr + weak_ptr.

class OwnershipContainer {
public:
    void add(std::shared_ptr<Obj> obj) {
        objects.push_back(obj);
    }
    std::shared_ptr<Obj> get(std::size_t i) { return objects[i]; }
private:
    std::vector<std::shared_ptr<Obj>> objects;
};


class NonOwnershipContainer {
public:
    void add(std::shared_ptr<Obj> obj) {
        objects.push_back(obj);
    }
    std::shared_ptr<Obj> get(std::size_t i) { return objects[i].lock(); }
private:
    std::vector<std::weak_ptr<Obj>> objects;
};

int main() {
    NonOwnershipContainer nonOwnershipContainer;
    {
        OwnershipContainer ownershipContainer;
        ownershipContainer.add(std::make_shared<Obj>(1));

        nonOwnershipContainer.add(ownershipContainer.get(0));
    }
    auto pobj = nonOwnershipContainer.get(0); // no more dangling pointer, pobj == nullptr
}

But in this case, I pay for reference counter, and it is philosophically wrong: with only one owner use shared_ptr.


回答1:


You actually do have shared ownership: When you access the object via the NonOwningContainer-contained pointer-like thing, you must take ownership, or the object may disappear out from under you while you're working with it.

Since you can't guarantee the object won't disappear out from under you:

But i cannot give guarantee that lifetime of Obj match or exceed lifetime of Non-owner container.

then your only option is to share ownership. Hence shared_ptr and weak_ptr is the appropriate approach.

Also, depending on the difference in lifetime of OwnershipContainer and NonOwnershipContainer, be aware of the interaction between std::make_shared and std::weak_ptr.



来源:https://stackoverflow.com/questions/43569581/non-ownership-copies-of-stdunique-ptr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!