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

C++ shared_ptr调用函数的API设计疑问:*data.get()是否为设计异味?

C++中shared_ptr传递方式的疑问解答
struct Data { /* ... */ };
int SomeFunction1(const Data& data) { return 0; }
int SomeFunction2(std::shared_ptr<Data>& data) { return 0; } // 此处为非const引用
int SomeFunction3(const Data* data) { return 0; } // 可能接收空指针

int main()
{
  auto data = std::make_shared<Data>(); /* 初始化逻辑 */;
  return SomeFunction1(*data.get()); // (1) 调用get并解引用指针
  return SomeFunction2(data); // (2) 设计接收shared_ptr的API
  return SomeFunction3(data.get()); // (3) 设计接收裸指针的API
}

关于*data.get()的写法

*data.get()功能上完全可行,但并不常见,属于冗余写法。因为std::shared_ptr已经重载了解引用运算符operator*(),直接写*data就能达到完全一致的效果,且更简洁、符合C++的惯用编码风格。

方式(1)的合理性分析

你认为方式(1)更可取的判断是正确的,理由如下:

  • 通用性最强:无论调用方持有shared_ptr、unique_ptr还是栈上的Data实例,都能直接传递给接受const Data&的函数,无需任何适配代码。
  • 安全性更高:引用不能为空,API无需处理空指针场景,避免了潜在的空指针解引用风险;同时const修饰明确函数仅读取Data内容,语义清晰。
  • 性能最优:传递引用不需要拷贝智能指针,也无额外指针操作开销,效率最高。

*data.get()是否属于设计异味

它算不上严重的设计异味,只是不够地道的编码风格。这种写法暴露了底层指针操作,而智能指针的核心价值之一就是封装指针操作、简化内存管理,直接调用get()再解引用,有点违背智能指针的设计初衷,换成*data更符合封装原则。

另外两种方式的局限性

  • 方式(2):接受std::shared_ptr<Data>&(非const引用)意味着函数可能会修改智能指针本身(比如重置、替换指向对象)。若API不需要此类操作,这种写法会强制调用方必须使用shared_ptr,大幅降低API通用性,只读场景不推荐使用。
  • 方式(3):接受const Data*允许传递空指针,API内部必须额外处理空值逻辑,增加复杂度;若确定不会传空值,使用引用比指针更安全。

总结

方式(1)的API设计是正确方向,但调用时建议将*data.get()改为*data,既简洁又符合C惯用写法。如果函数不需要管理对象生命周期,优先选择传递const T&(只读场景)或T&(可写场景),这是C传递对象的最佳实践之一。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:23:13