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

C++ shared_ptr最佳实践:字符串转大写示例代码问题与优化分析

关于C++智能指针使用的代码问题分析

这段小程序原本声称使用了智能指针,省去调用者手动free()返回缓冲区的麻烦,同时还能避免调用者忘记释放内存的问题,对应原始代码如下:

char* toupper(const string& s){
  string ret(s.size(), char());
  for(unsigned int i = 0; i < s.size(); ++i)
    ret[i] = (s[i] <= 'z' && s[i] >= 'a') ? s[i]-('a'-'A') : s[i];
  return (char*) memcpy(
   chkedAlloc(1+ret.size(),*std::make_shared<char*>(nullptr)),
   ret.c_str(), 1+ret.size()
  );
}

其中chkedAlloc(n,A)会在捕获std::bad_alloc异常后返回new A[n]。

这段代码乍一看像是智能指针简化开发、提升安全性的教科书级用法,但实际上存在不少问题和可优化空间,以下是具体的改进点评:

  • 最优方案是直接返回string对象,其析构函数会在对象离开作用域时自动释放关联的存储空间,完全不需要手动管理堆内存。
  • 原代码属于「shared_ptr作为最后备选」的典型反例:shared_ptr的运行开销远高于unique_ptr,没有共享所有权需求时完全没必要使用shared_ptr。
  • 这里需要纠正两个常见的错误认知:
    • 不要误以为shared_ptr是全场景线程安全的
    • 不要误以为unique_ptr无法转移给其他持有者
      实际上持有者完全可以转移unique_ptr的所有权,只是同一时间仅能有一个持有者持有所有权,完全满足这个场景的需求。
  • 转大写的逻辑可以考虑使用标准模板算法std::transform实现,代码更简洁易维护。
  • 如果示例代码是为了演示智能指针用法,可以优先选用int作为示例类型而非std::string,能规避各类无关讨论。

优化后的参考实现如下:

unique_ptr<char*> toupper(const string& s){
  string ret(s.size(), char());
  for(unsigned int i = 0; i < s.size(); ++i)
    ret[i] = (s[i] <= 'z' && s[i] >= 'a') ? s[i]-('a'-'A') : s[i];
  char *p = new char[1+ret.size()]; // 可自行补充try/catch(std::bad_alloc)逻辑
  return make_unique<char*>((char*) memcpy(p, ret.c_str(), 1+ret.size()));
}
void f() { string s = "hello"; .. 
  { char* p = *toupper(s); // 该作用域现在持有指针所有权
  } // 离开作用域:堆上分配的内存由智能指针自动释放
..
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:09:01