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

std::shared_ptr的.get()是否复制对象?相关未定义行为探讨

关于std::shared_ptr与原始指针/对象混用的问题分析

场景1:原始指针指向shared_ptr管理的对象

先看以下代码:

#include <iostream>
#include <memory>

using namespace std;

class myClass{
    public:
    int a = 15;
    myClass(int x): a(x){};
    ~myClass(){cout << "die die ";};
};

int main()
{
    myClass* c;
    
    {
    std::shared_ptr<myClass> a = std::make_shared<myClass>(16);
    cout<< a.use_count(); //1
    std::shared_ptr<myClass> b = a;
    cout<< a.use_count(); //2
    c = a.get();
    cout<< a.use_count(); // still 2
    } // die die
    
    cout << (*c).a; // 16? UB?

    return 0;
}

关键分析:

  • std::shared_ptr::get()仅返回智能指针管理的原始指针,不会复制对象,因此引用计数不会变化。
  • 代码块结束时,a和b的生命周期结束,引用计数降为0,对应的堆对象被析构(输出"die die")。此时c指向的内存已经被释放,后续访问(*c).a属于未定义行为——你可能碰巧读到旧值,但这完全不可靠,程序随时可能崩溃。
  • 若执行delete c,会导致重复释放已被智能指针回收的内存,直接引发程序崩溃,这类操作风险极高,绝对禁止。

场景2:对象赋值(从shared_ptr管理的对象复制)

再看补充场景的代码:

int main()
{
    myClass c(5);
    
    {
    std::shared_ptr<myClass> a = std::make_shared<myClass>(16);
    cout<< a.use_count(); //1
    std::shared_ptr<myClass> b = a;
    cout<< a.use_count(); //2
    c = *(a.get()); // 写法粗糙,但这是在复制对象吗?
    cout<< a.use_count(); // still 2
    }// die die
    
    cout << (c).a; //16

    return 0;
}// die die

关键分析:

  • c = *(a.get())是对象赋值操作:它将智能指针管理的堆对象的内容,复制到栈上的c对象中(调用类的默认赋值运算符,因为未自定义)。
  • 这种操作是安全的:栈上的c和智能指针管理的堆对象是两个完全独立的实例。代码块结束时堆对象被析构(第一次输出"die die"),程序结束时栈对象c被析构(第二次输出"die die"),两次析构针对不同对象,无任何冲突。
  • get()在这里仅用于获取堆对象的原始指针,进而解引用得到对象本身,赋值操作完全独立于智能指针的管理逻辑,不会影响引用计数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:23:14