从另一个唯一 ptr 的原始 ptr 创建唯一的 ptr



当我使用另一个唯一指针的原始指针创建唯一指针时会发生什么?在下面的示例中,调用创建第二个类时会发生什么?我以为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_ptrstd::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_;
};

如果您真的希望FirstClassSecondClass共享相同的指针,请使用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_;
};

最新更新