当我使用另一个唯一指针的原始指针创建唯一指针时会发生什么?在下面的示例中,调用创建第二个类时会发生什么?我以为first_obj_在创建second_obj_时会放弃所有权,但是当调用get时first_obj_不会放弃所有权。
class SecondClass {
SecondClass(Object* obj) : second_obj_(obj) {}
.....
private:
std::unique_ptr<Obj> second_obj_;
}
class FirstClass {
FirstClass() {
std::unique_ptr<Obj> first_obj_ = std::make_unique<Obj>();
}
std::unique_ptr<SecondClass> CreateSecondClass() {
std::make_unique<Obj>(first_obj_.get());
}
.....
private:
std::unique_ptr<Obj> first_obj_;
SecondClass second_class;
}
当我使用另一个唯一指针的原始指针创建唯一指针时会发生什么情况?
坏事可能发生!
您最终会得到 2 个unique_ptr
对象,它们都认为自己是原始指针的独占所有者,因此这两个对象都将尝试管理并最终释放拥有的内存。 为了避免这种情况,您必须将所有权从一个unique_ptr
传递到另一个,或者至少为unique_ptr
中的一个提供不释放内存的自定义deleter
(在这种情况下,您不应该首先使用 2 个unique_ptr
对象(。
在下面的示例中,调用创建第二个类时会发生什么?
first_obj_
和second_obj_
最终都会持有指向内存中同一Object
的指针,并且它们都将尝试delete
它。
我以为
first_obj_
会在创建second_obj_
时放弃所有权
否,因为unique_ptr::get()
只是返回原始指针的副本,所以它不会释放指针的所有权。 如果需要,请改用unique_ptr::release()
:
class SecondClass {
public:
SecondClass(Object* obj) : second_obj_(obj) {}
...
private:
std::unique_ptr<Object> second_obj_;
};
class FirstClass {
public:
FirstClass() : first_obj_(std::make_unique<Object>()) {}
std::unique_ptr<SecondClass> CreateSecondClass() {
return std::make_unique<SecondClass>(first_obj_.release());
}
...
private:
std::unique_ptr<Object> first_obj_;
};
否则,您可以简单地将一个unique_ptr
std::move
到另一个:
class SecondClass {
public:
SecondClass(std::unique_ptr<Object> obj) : second_obj_(std::move(obj)) {}
...
private:
std::unique_ptr<Object> second_obj_;
};
class FirstClass {
public:
FirstClass() : first_obj_(std::make_unique<Object>()) {}
std::unique_ptr<SecondClass> CreateSecondClass() {
return std::make_unique<SecondClass>(std::move(first_obj_));
}
...
private:
std::unique_ptr<Object> first_obj_;
};
如果您真的希望FirstClass
和SecondClass
共享相同的指针,请使用std::shared_ptr
而不是std::unique_ptr
:
class SecondClass {
public:
SecondClass(std::shared_ptr<Object> obj) : second_obj_(obj) {}
...
private:
std::shared_ptr<Object> second_obj_;
};
class FirstClass {
public:
FirstClass() : first_obj_(std::make_shared<Object>()) {}
std::unique_ptr<SecondClass> CreateSecondClass() {
return std::make_unique<SecondClass>(first_obj_);
}
...
private:
std::shared_ptr<Object> first_obj_;
};
如果你想放弃所有权,你应该使用release()
。
std::unique_ptr
无法知道您将如何处理用get()
提取的指针,特别是它无法知道您决定将其交给另一个std::unique_ptr
。
如果两个std::shared_ptr
将存储相同的指针,您将获得对象的双delete
,即未定义的行为。
但是,如果要将所有权从一个std::unique_ptr
传递到另一个,则可能应该改用移动语义:
class Obj {};
struct SecondClass {
SecondClass(std::unique_ptr<Obj>&& obj) : second_obj_(std::move(obj)) {}
private:
std::unique_ptr<Obj> second_obj_;
};
struct FirstClass {
FirstClass() {
first_obj_ = std::make_unique<Obj>();
}
std::unique_ptr<SecondClass> CreateSecondClass() {
return std::make_unique<SecondClass>(std::move(first_obj_));
//note that first_obj_ points to nullptr now. Only SecondClass owns the Obj.
}
private:
std::unique_ptr<Obj> first_obj_;
};