问题
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