基础数据类型赋值运算符与临时对象:C++悬空指针疑问问询
你的unique_ptr悬空指针疑问拆解
嘿,这个问题挺典型的,咱们一步步把它说透!首先得给你拍板:你最初的判断是对的——puter确实是悬空指针,你运行时没出问题只是撞上了C++里的「未定义行为」,这可不是代码没问题哦!
先给你捋清楚底层到底发生了什么:
- 当你调用
std::make_unique<int>(50)时,程序会在堆上开辟一块内存存50,同时返回一个临时的unique_ptr<int>对象——这个临时对象是这块堆内存的「唯一主人」,负责最后销毁它。 - 你调用
.get()的时候,只是从这个临时unique_ptr手里拿到了它内部存的裸指针,但完全没拿走所有权——临时unique_ptr还是牢牢握着这块内存的处置权。 - 关键来了:C++里的临时对象,生命周期只到「包含它的完整表达式结束」为止。这里的完整表达式就是
puter = std::make_unique<int>(50).get();这整行语句。等这行代码执行完,那个临时unique_ptr就会被销毁,它的析构函数会立刻把手里的堆内存给释放掉。 - 这时候
puter存的裸指针,就指向了一块已经被操作系统回收的内存——也就是咱们说的悬空指针。之后你解引用*puter的行为属于「未定义行为」:有时候碰巧内存还没被覆盖,你能读到原来的50;有时候直接崩溃;甚至可能出现更诡异的结果,完全看运气和运行环境,绝对不能依赖。
你之前猜是不是「unique_ptr的资源被移动赋值给了puter」,其实不对——puter是个裸指针,unique_ptr的所有权转移只发生在unique_ptr对象之间,裸指针接不住这个所有权。如果想安全地用这块内存,你应该把puter声明成std::unique_ptr<int>类型,直接赋值:
std::unique_ptr<int> puter = std::make_unique<int>(50); if(puter) { std::cout << *puter << std::endl; }
这样puter就成了这块内存的新主人,直到它自己被销毁时才会释放内存,完全安全。
说白了,你的代码本质上是有问题的,运行时没报错只是运气好,这种写法绝对不能出现在生产代码里哦!
内容的提问来源于stack exchange,提问作者Shrouded
相关产品推荐
相关产品推荐

