C++_unique_ptr_一个类Frame的普通指针fr初始化一个unique_ptr, 这个普通指针还有管理权吗?
一个类Frame的普通指针fr初始化一个unique_ptr, 这个普通指针还有管理权吗?
在 C++ 中,std::unique_ptr
是一种智能指针,它独占管理其所指向对象的所有权。一旦你用一个普通指针初始化或赋值给一个 std::unique_ptr
,这个 unique_ptr
会接管对象的所有权,并且不允许其他指针管理这个对象的生命周期。
让我们来看如下代码示例:
Frame* fr = new Frame(); // 普通指针,动态分配内存
mypFrame = std::unique_ptr<Frame>(fr); // 用普通指针初始化unique_ptr
解释:
-
Frame* fr = new Frame();
- 这行代码动态分配了一个
Frame
对象,并用普通指针fr
指向它。此时fr
拥有对Frame
对象的管理权,负责释放该对象的内存。
- 这行代码动态分配了一个
-
mypFrame = std::unique_ptr<Frame>(fr);
- 这行代码将普通指针
fr
赋给了一个std::unique_ptr
,mypFrame
现在接管了fr
所指向的对象的管理权。 - 一旦
mypFrame
拥有了对象的所有权,普通指针fr
将 不再拥有管理权,并且你不能再安全地使用fr
进行内存管理。尤其是,fr
不应被delete
,否则会导致 双重释放 的问题,因为mypFrame
会在超出作用域时自动释放该对象。
- 这行代码将普通指针
重要注意:
- 普通指针
fr
不再具有管理权:虽然fr
仍然可以指向该对象,但它不再负责释放内存。现在std::unique_ptr
拥有该对象的所有权并将在合适的时候释放它。 - 如果你尝试对
fr
执行delete fr;
,这会导致 双重释放(Double Free)问题,因为std::unique_ptr
会自动在其析构时释放Frame
对象。
进一步说明:
std::unique_ptr
通过其构造函数接管对象的所有权。这意味着对象的生命周期完全由unique_ptr
控制,而普通指针fr
丧失了管理权。- 在使用
unique_ptr
后,最好将fr
置为nullptr
或停止使用它,因为它不再安全地管理对象。
安全使用示例:
Frame* fr = new Frame(); // 普通指针
std::unique_ptr<Frame> mypFrame(fr); // 将管理权转移给unique_ptr
fr = nullptr; // 明确将普通指针设为nullptr以防止错误使用
在这个示例中,我们显式地将 fr
设置为 nullptr
,以避免意外地使用它来管理已被 unique_ptr
接管的内存。
总结:
- 一旦
std::unique_ptr
接管了普通指针指向的对象,普通指针将 不再拥有管理权。 - 在转移所有权后,避免使用普通指针来操作该对象,尤其是不要手动调用
delete
,以防止内存管理问题。
当 mypFrame
= std::unique_ptr<Frame>(fr); 时, 会对 fr所指向的Frame对象进行析构吗?
在执行 mypFrame
= std::unique_ptr<Frame>(fr);
时,不会立即对 fr
所指向的 Frame
对象进行析构。实际上,此时只是将 fr
所指向的对象的管理权转移给了 std::unique_ptr
。具体过程如下:
过程解释:
Frame* fr = new Frame(); // 动态分配内存,fr指向一个新的Frame对象
mypFrame = std::unique_ptr<Frame>(fr); // 将fr指向的对象的管理权转移给unique_ptr
-
Frame* fr = new Frame();
:- 这行代码在堆上动态分配了一个
Frame
对象,并返回一个指向该对象的普通指针fr
。此时fr
负责管理这个Frame
对象的内存,只有通过delete fr;
才能释放这个对象。
- 这行代码在堆上动态分配了一个
-
mypFrame
= std::unique_ptr<Frame>(fr);
:- 这行代码创建了一个
std::unique_ptr<Frame>
,将fr
所指向的对象的管理权交给mypFrame
。 - 这里
std::unique_ptr
接管了fr
的指针,但 不会析构或释放Frame
对象,因为此时unique_ptr
还没有释放对象的时机。只有当mypFrame
离开作用域或被重新赋值时,才会对其管理的对象进行析构。 - 注意:
fr
仍然可以指向那个Frame
对象,但它不再拥有管理权,也不应被手动delete
,否则会导致std::unique_ptr
之后进行双重释放。
- 这行代码创建了一个
何时析构:
对象的析构发生在 std::unique_ptr
销毁或重新赋值时,而不是在初始化时。因此,Frame
对象会在以下情况下被析构:
- 当
mypFrame
离开其作用域时:- 如果
mypFrame
是一个局部变量,当它离开作用域时,std::unique_ptr
的析构函数会被调用,自动释放它所管理的Frame
对象,并调用该对象的析构函数。
- 如果
- 当
mypFrame
被赋值为另一个std::unique_ptr
时:- 如果
mypFrame
之前已经管理了一个对象,在赋值前会先释放当前管理的对象,然后接管新对象。例如:
- 如果
mypFrame = std::make_unique<Frame>(); // 先析构原对象,然后管理新对象
小结:
- 不会立即析构:当你执行
mypFrame
= std::unique_ptr<Frame>(fr);
时,fr
所指向的Frame
对象不会被立即析构,而是将对象的管理权转移给mypFrame
。 - 何时析构:
Frame
对象的析构发生在std::unique_ptr
被销毁、超出作用域或被赋值新的对象时。 - 避免手动删除
fr
:一旦unique_ptr
接管对象,fr
不再拥有管理权,手动调用delete
会导致双重释放问题。