C++新手求教:unique_ptr调用get()两种写法为何结果不同?
为什么从临时
unique_ptr获取的裸指针会失效? 嘿,这个问题问得太到位了,刚好踩中了std::unique_ptr最容易被新手忽略的生命周期陷阱!咱们一步步拆解两种写法的本质区别:
第一种写法:从临时unique_ptr拿裸指针
auto w = (std::make_unique<Wall>()).get();
这里std::make_unique<Wall>()创建的是一个没有名字的临时unique_ptr对象。C++里临时对象的生命周期非常短——它只存在于当前这条语句执行期间,等到分号;一出现,这个临时unique_ptr就会被立刻销毁。
而unique_ptr的核心职责就是管理对象的生命周期:当它被销毁时,会自动调用delete释放它持有的内存。所以这条语句执行完,w虽然拿到了一个非空的裸指针,但它指向的Wall对象已经被临时unique_ptr销毁了!
这时候你做空值检查,w的地址确实不是nullptr(因为之前get()返回的是有效的内存地址),但那块内存已经被归还给系统了。后续使用w的时候,要么是读取已经释放的内存(无效读取),如果你的代码里还尝试手动delete w,就会触发Valgrind报的“双重删除”——因为Wall已经被临时unique_ptr删过一次了。
第二种写法:从命名unique_ptr拿裸指针
auto wall = std::make_unique<Wall>(); auto w = wall.get();
这里的wall是一个命名的unique_ptr变量,它的生命周期和普通变量一样:从定义的位置开始,直到它所在的作用域结束(比如函数执行完毕,或者它被手动销毁)。只要wall还活着,它就会牢牢持有Wall对象的所有权,不会自动释放内存。
所以w作为裸指针指向的是wall管理的有效内存,只要wall没被销毁,w就能安全使用(当然,你得保证不会在wall销毁后继续用w,那又是另一个悬空指针问题了)。
核心总结
- 永远不要从临时智能指针中获取裸指针,因为临时对象的生命周期太短,会立刻释放内存,导致裸指针变成悬空指针。
unique_ptr的核心是所有权管理,命名的智能指针会在作用域内维持对象的生命周期,而临时智能指针只会活过当前语句。
内容的提问来源于stack exchange,提问作者z6318
相关产品推荐
相关产品推荐

