shared_ptr::get()返回裸指针T*,不增引用计数、不管理所有权,仅用于C接口等需原始指针的场景;误用会导致悬空指针或双重释放,应优先传递shared_ptr本身。

shared_ptr::get() 返回的是裸指针,不是智能指针
shared_ptr::get() 只返回内部管理的原始指针(T*),不增加引用计数,也不参与所有权管理。它常用于需要传裸指针给 C API、第三方库或 legacy 接口的场景,比如 glTexImage2D、fopen_s 或某些只接受 const char* 的函数。
常见错误是误以为用 get() 获得的指针能“接管”生命周期 —— 实际上它只是个快照,shared_ptr 一释放,这个指针立刻悬空。
- 永远不要用
delete手动释放get()返回的指针 - 避免长期保存该指针(比如存入全局 map 或缓存)
- 若需延长生命周期,应传递
shared_ptr本身,而非调用get()
什么时候必须用 get()?哪些情况其实不该用?
必须用:C 接口明确要求裸指针且不复制所有权,例如 sqlite3_bind_blob(stmt, idx, ptr, size, SQLITE_STATIC) 中的 ptr;或调试时打印地址:printf("addr: %p", ptr.get());。
不该用:往另一个 shared_ptr 构造函数里传 get() 结果 —— 这会触发双重 delete:
立即学习“C++免费学习笔记(深入)”;
auto sp = std::make_shared<int>(42); std::shared_ptr<int> bad(sp.get()); // ❌ 悬空 + double-free
正确做法是拷贝原 shared_ptr:
std::shared_ptr<int> good = sp; // ✅ 引用计数 +1
- 传参给接受
const T*的函数(如std::string_view构造)可用get(),但优先考虑是否支持直接传shared_ptr或std::string - 做指针比较(
if (p.get() == q.get()))可行,但更安全的是用operator==比较两个shared_ptr
get() 和 get() 返回值为空时的行为
shared_ptr::get() 在智能指针为空(!ptr)时返回 nullptr,不会抛异常。这和 operator->() 不同 —— 后者解引用空 shared_ptr 是未定义行为。
所以安全写法是先判空再用 get():
if (ptr) {
some_c_api(ptr.get(), ptr.size()); // 假设 ptr 是 shared_ptr<vector<char>>
}
- 不要假设
get()总是非空;尤其在函数参数可能为默认构造的shared_ptr时 -
get()返回类型是T*,对const对象返回const T*,类型严格匹配 - 不能对
shared_ptr<void></void>调用get()(无意义,编译报错)
性能与 ABI 兼容性影响很小,但语义风险很高
get() 是纯内联函数,零开销;它不触发任何内存操作或原子计数更新。问题不在性能,而在语义混淆:一旦你开始频繁依赖 get(),说明设计可能已偏离 RAII 原则。
典型信号包括:
- 大量
get()+ 手动memcpy/strlen/strcmp - 把
get()结果传给需要长期持有指针的回调(没绑定shared_ptr的生命周期) - 在多线程中裸指针跨线程传递,却没确保
shared_ptr的生存期覆盖整个使用过程
真正难处理的从来不是怎么调用 get(),而是怎么证明那个裸指针在使用期间绝不会 dangling —— 这往往需要人工推理,没法靠编译器检查。


















