You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于shared_ptr移动语义的疑问:make_shared赋值后原指针为何仍有效

核心错误理解纠正

你当前的代码完全没有触发shared_ptr的移动语义,make_shared<Test>(*p1)操作和shared_ptr的所有权转移没有任何关系,这是你认知偏差的核心来源。


你的代码实际执行逻辑

make_shared<Test>(*p1)的执行流程如下:

  • 第一步:对p1解引用拿到Test&类型的对象引用,也就是p1当前持有的Test实例本身
  • 第二步:以这个实例为参数,调用Test类的拷贝构造函数(你没有自定义拷贝构造,编译器会生成默认版本),创建一个全新的、独立的Test堆对象
  • 第三步:返回指向这个新Test对象的shared_ptr,赋值给p2

整个过程中p1的所有权没有发生任何变更,它仍然持有原始Test对象的所有权,引用计数始终为1,自然可以正常调用Disp()方法。你可以观察这段代码的运行输出,会出现两次Dest打印,也验证了存在两个独立的Test对象。


正确触发shared_ptr移动语义的写法

如果要实现shared_ptr的所有权转移,需要显式调用移动构造,写法如下:

int main()
{
 Test *p = new Test();
 shared_ptr<Test> p1(p);
 shared_ptr<Test> p2 = std::move(p1); // 显式移动构造,转移所有权

 // 此时p1已经被置空,后续访问p1属于未定义行为
 // p1->Disp(); // 这句话运行时大概率崩溃
 p2->Disp();
}

移动构造执行后,p1会被重置为空,不再持有任何对象的所有权,此时再访问p1就符合你之前的预期,属于非法操作。


额外最佳实践提醒

尽量避免用裸指针初始化shared_ptr,推荐直接使用make_shared创建对象,减少出现重复初始化、double free等问题的概率:

auto p1 = make_shared<Test>(); // 替代Test* p = new Test(); shared_ptr<Test> p1(p);

内容的提问来源于stack exchange,提问作者Nihal Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 12:57:02