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

std::unique_ptr悬空指针问题修复及clone()用法合理性咨询

C++代码修复与克隆模式实践分析

问题代码与现象

以下是运行的C++代码:

#include <memory>
#include <iostream>
class A {
public:
  virtual std::unique_ptr<A> clone() = 0;
};
class B : public A {
private:
  int b0;
public:
  B(const B& b) { b0 = b.get_b0(); }
  B(const int& b0) : b0(b0) {}
  std:: unique_ptr<A> clone() { return std::make_unique<B>(*this); }
  const int& get_b0() const { return b0; }
  int& get_b0() { return b0; }
};
class box {
private:
  std::unique_ptr<A> o;
public: 
  box(const box& sp) { o = sp.o->clone(); }
  box(std::unique_ptr<A> o)  : o(std::move(o)) {}
  std::unique_ptr<A> get_o() { return o->clone(); }
};
void foo(std::unique_ptr<box> sp) {
  std::unique_ptr<A> o = sp->get_o();
if(const B *ptr1 = dynamic_cast<const B*>(o.get()))
  std::cout << ptr1->get_b0() << std::endl;
if(const B *ptr = dynamic_cast<const B*>(sp->get_o().get()))
  std::cout << ptr->get_b0() << std::endl;
}
int main() {
  B b(100);
  box sp(std::make_unique<B>(b));
  foo(std::make_unique<box>(sp));
  return 0;
}

运行输出:

100  
3579964222 (some random integer!!!)

将std::unique_ptr替换为std::shared_ptr后代码可正常运行,但业务场景中shared_ptr可能引发问题(修改一个对象可能影响其他共享实例),现需修复代码并确认当前clone()用法是否为良好实践。


代码修复

错误原因

第二个if语句中,sp->get_o().get()返回的指针指向的是临时unique_ptr管理的对象:get_o()返回的unique_ptr是临时对象,在该行表达式执行完毕后就会被销毁,其管理的A对象也会被释放,导致ptr成为野指针,读取到随机内存值。而shared_ptr因为引用计数机制,临时对象销毁后只要还有其他引用就不会释放对象,所以不会出现问题,但这并非正确的解决方式。

修复方案

将临时的unique_ptr存储到变量中,确保对象生命周期覆盖指针的使用:

void foo(std::unique_ptr<box> sp) {
  std::unique_ptr<A> o = sp->get_o();
  if(const B *ptr1 = dynamic_cast<const B*>(o.get()))
    std::cout << ptr1->get_b0() << std::endl;
  // 修复:先保存临时unique_ptr,避免对象提前销毁
  std::unique_ptr<A> temp_o = sp->get_o();
  if(const B *ptr = dynamic_cast<const B*>(temp_o.get()))
    std::cout << ptr->get_b0() << std::endl;
}

clone()用法的合理性

当前的clone()设计属于原型模式的标准实现,是良好的代码实践:

  • 使用std::unique_ptr作为返回值,明确表达了克隆后对象的所有权完全转移给调用者,避免了共享所有权带来的意外修改问题,完全适配你的业务场景需求。
  • 虚函数clone()定义了基类的克隆接口,子类实现具体的克隆逻辑,符合面向对象的多态设计原则。
  • 可以进一步优化:将clone()声明为const成员函数,因为克隆操作不应该修改原对象,提升代码的const正确性:
    // 基类修改
    virtual std::unique_ptr<A> clone() const = 0;
    // 子类修改
    std::unique_ptr<A> clone() const override { return std::make_unique<B>(*this); }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:35:23