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

Setter方法中使用make_shared却表现为创建副本的原因排查

问题分析与解决思路

嘿,这个问题我之前帮好几个开发者排查过,核心问题大概率出在你传递对象的方式和智能指针初始化的逻辑上,咱们一步步拆解:

最可能的错误原因

你大概率是在setPart()方法里做了「对象拷贝」,而不是让智能指针直接指向原对象的内存。举个典型的错误代码例子:

// 假设你的类是这样的
class YourClass {
private:
    std::shared_ptr<Part> m_part;
public:
    // 这里用了值传递,会创建some_part的副本
    void setPart(Part some_part) {
        // 用副本创建了一个新的Part对象,m_part指向这个新副本
        m_part = std::make_shared<Part>(some_part);
    }
};

这种情况下,当你把some_part传入setPart()时,参数some_part是原对象的临时副本,之后你用这个副本在堆上创建了一个全新的Part实例,m_part指向的是这个新实例,和你原来的some_part完全是两个独立的对象。所以你修改原some_part的属性时,m_part指向的对象根本不会有变化。

正确的实现方式

要让m_part和原对象同步变化,核心是让智能指针直接指向原对象的内存地址,而不是创建副本。分两种场景处理:

场景1:原对象在堆上(推荐)

如果你的some_part本来就是在堆上创建的,那直接传递智能指针(或者转移所有权,看你用的智能指针类型):

// 用shared_ptr传递,共享所有权
void setPart(std::shared_ptr<Part> part) {
    m_part = part;
}

// 调用的时候
auto some_part = std::make_shared<Part>();
yourObj.setPart(some_part);

// 此时修改some_part->属性,m_part->属性会同步变化
some_part->name = "new name";

场景2:原对象在栈上(需注意生命周期)

如果some_part是栈上对象,不能直接用智能指针接管(会导致栈对象被智能指针释放,触发double free),这时可以用std::reference_wrapper来持有引用,或者直接存原始引用(但要确保原对象的生命周期比YourClass实例长):

#include <functional> // 要包含这个头文件

class YourClass {
private:
    std::reference_wrapper<Part> m_part;
public:
    void setPart(Part& part) {
        m_part = part;
    }

    // 访问的时候用.get()获取原对象
    Part& getPart() {
        return m_part.get();
    }
};

// 调用的时候
Part some_part;
yourObj.setPart(some_part);

// 修改some_part,m_part对应的对象也会变
some_part.name = "new name";

额外注意点

  • 如果用的是std::unique_ptr,它是独占所有权的,传递时需要用std::move转移所有权,比如:
    void setPart(std::unique_ptr<Part> part) {
        m_part = std::move(part);
    }
    
    但这种情况下原对象的所有权会转移到m_part,原unique_ptr会变成空指针,根据你的需求选择。

简单来说,你现在的代码相当于给智能指针塞了个原对象的“双胞胎兄弟”,俩兄弟互不影响;要让它们同步,就得让智能指针直接“绑定”原对象本身。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:11:05