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

C++修改std::vector存储对象值失效 如何正确存储可修改对象?

问题根源

该问题的核心是lambda捕获的this指针不会随对象拷贝自动更新,和std::vector的存储特性相关,具体逻辑如下:

  • 你在Thing的构造函数里创建的lambda捕获了当前对象的this指针,这个指针指向构造时的原始对象(也就是你代码里的局部变量a)
  • 调用mythings.push_back(a)时,会调用Thing的默认拷贝构造函数生成一个新的Thing对象存入vector,默认拷贝构造只会原样复制父类的myfuncs容器,里面lambda保存的this还是原来局部变量a的地址
  • 后续你调用mythings[0].setValue修改的是vector里新对象的value,但lambda执行时访问的是原局部变量a的value,这个值从初始化后就没被修改过,默认值为0,所以输出一直是0
解决方案

有两种常用的方案可以解决这个问题:

方案1:容器存储智能指针,避免对象拷贝

直接让容器存储std::unique_ptr<Thing>或者std::shared_ptr<Thing>,对象只会被构造一次,不会发生拷贝,lambda捕获的this始终指向正确的对象。修改后的main函数代码如下:

int main() {
    std::vector<std::unique_ptr<Thing>> mythings;
    // 直接构造对象存入智能指针,不需要额外的局部变量
    mythings.push_back(std::make_unique<Thing>());
    
    mythings[0]->setValue(666);
    mythings[0]->toggle();
    mythings[0]->setValue(999);
    mythings[0]->toggle();
    return 0;
}

方案2:自定义拷贝逻辑,更新lambda的this指针

如果你确实需要在容器里存储对象本身,就要为Thing类实现自定义的拷贝构造、拷贝赋值函数,拷贝时重新生成绑定了新对象this的lambda,替换掉复制过来的旧lambda:

class Thing: public OtherThing{
public:
    Thing(){
        std::function<int()> myfunc= [this]()->int{
            std::cout << "from lambda " << this->value << std::endl;
            return this->value;
            };
        this->addElement(myfunc);
    }
    // 自定义拷贝构造函数
    Thing(const Thing& other){
        value = other.value;
        // 重新生成绑定当前新对象this的lambda
        std::function<int()> myfunc= [this]()->int{
            std::cout << "from lambda " << this->value << std::endl;
            return this->value;
            };
        this->addElement(myfunc);
    }
    // 自定义拷贝赋值运算符
    Thing& operator=(const Thing& other){
        if (this != &other) {
            value = other.value;
            // 清空旧的lambda,添加新的绑定当前this的lambda
            myfuncs.clear();
            std::function<int()> myfunc= [this]()->int{
                std::cout << "from lambda " << this->value << std::endl;
                return this->value;
                };
            this->addElement(myfunc);
        }
        return *this;
    }
    void setValue(int value){
        this->value = value;
    }
    int getValue(){
        return this->value;
    }
private:
    int value = 0;
    // 注意要让子类能访问父类的myfuncs,可以把父类的myfuncs改为protected权限,或者在父类提供修改接口
};

一般来说方案1的实现成本更低,也更符合C++的常规使用习惯,推荐优先使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:36:03