能否从std::unique_ptr<T>创建带移动构造函数的T类型栈变量?
从std::unique_ptr安全创建栈上T对象的正确姿势
咱们先拆解下你原来写法的问题:
std::unique_ptr<T> p = ext_get_my_pointer(); T val{std::move(*p.release())};
这里的p.release()是个隐形大坑——它会把unique_ptr持有的裸指针直接“交出去”,从此不再负责这块内存的释放。如果移动构造val的过程中抛出异常,那个裸指针指向的内存就彻底没人管了,直接造成泄漏;就算移动构造成功,你也没手动delete这个指针,同样会导致内存泄漏,这就是你担心的根源。
更简洁又安全的写法
其实完全没必要用release(),直接利用unique_ptr的自动管理特性就行:
std::unique_ptr<T> p = ext_get_my_pointer(); T val = std::move(*p); // 要是之后不用p了,可以提前reset掉,省得等p出作用域才析构原对象 p.reset();
这么做的好处一目了然:
- 代码清爽多了,不用跟裸指针打交道
- 绝对安全:哪怕移动构造抛异常,
unique_ptr还攥着原对象的所有权,析构时会自动释放内存,不会漏 - 移动完成后,原对象虽然被“掏空”了,但处于标准允许的“可析构”状态,
unique_ptr析构它完全没问题
更紧凑的写法(如果不需要保留p)
要是拿到智能指针后马上就要转成栈变量,甚至可以一行搞定:
T val = std::move(*ext_get_my_pointer());
这里临时的unique_ptr会在这行代码结束后自动析构,不管移动成功失败都能妥善处理内存。
为啥你的写法会别扭?
release()本来是给那些需要把所有权转移给裸指针或者其他智能指针的场景用的,不是用来提取对象做移动构造的。直接解引用unique_ptr然后移动,才是符合它设计初衷的用法哦。
内容的提问来源于stack exchange,提问作者Touloudou
相关产品推荐
相关产品推荐

