首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >性病向量c++中对象值的变化

性病向量c++中对象值的变化
EN

Stack Overflow用户
提问于 2021-10-09 21:17:18
回答 2查看 353关注 0票数 2

我注意到我无法更改存储在std::vectorstd::map中的对象的值。下面代码的输出为"0"提供了toggle()函数调用的结果,在这两种情况下。在向量之外直接使用对象时,不存在此行为。我是不是遗漏了一些关于std::vector或类似容器的东西?如何正确地将对象存储在容器中并保持更改其值的能力?

代码语言:javascript
复制
#include <iostream>
#include <functional>
#include <vector>

class OtherThing{
public:
void addElement(std::function<int()> func){
    this->myfuncs.push_back(func);
}
void toggle(){
    std::cout << "toggle .. " << this->myfuncs[0]() << std::endl;
}
private:
std::vector<std::function<int()>> myfuncs; 
};

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);
    }
void setValue(int value){
    this->value = value;
}
int getValue(){
    return this->value;
}
private:
int value;
};


int main() {
    // container for things 
    std::vector<Thing> mythings;
    // a thing
    Thing a;
    
    mythings.push_back(a);
    
    mythings[0].setValue(666);
    
    mythings[0].toggle();
    mythings[0].setValue(999);
    mythings[0].toggle();
    return 0;
}

产出:

代码语言:javascript
复制
clang++-7 -pthread -std=c++17 -o main main.cpp
./main
toggle .. from lambda 0
0
toggle .. from lambda 0
0
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-10-09 22:01:13

push_back(a)复制了一份amythings[0]返回对该副本的引用。因此,任何修改mythings[0]成员的操作都不会反映在a中,反之亦然。

然而,当apush_back()复制时,Thing的编译器生成的复制构造函数将按原样复制myfuncs向量,因此a的构造函数存储在该向量中的lambda也被复制为- is -,该this指针捕获了指向athis指针,而不是新的副本。

因此,当您调用mythings[0].setValue()时,您正在修改复制的Thingvalue,但是当您调用mythings[0].toggle()时,您调用的是一个打印avalue的lambda --它从一开始就没有初始化过,所以在调用a.setValue()之前输出是不确定的。

要解决这个问题,您需要为Thing实现自己的复制构造函数,该构造函数存储自己的lambda,捕获复制的Thingthis指针,而不是从正在复制的Thing中存储以前的lambda的副本,例如:

代码语言:javascript
复制
Thing(const Thing &src){
    value = src.value;
    std::function<int()> myfunc = [this]()->int{
        std::cout << "from copied lambda " << this->value << std::endl;
        return this->value;
    };
    this->addElement(myfunc);
}

在线演示

票数 2
EN

Stack Overflow用户

发布于 2021-10-10 12:33:17

我也是根据这些评论来尝试的。老实说,我不喜欢这样。脚本太多,不能调用toggle()

代码语言:javascript
复制
#include <iostream>
#include <functional>
#include <vector>

class Thing;

class OtherThing{
public:
void addElement(std::function<int(Thing*)> func){
    this->myfuncs.push_back(func);
}
void toggle(Thing* obj){
    std::cout << "toggle .. " << this->myfuncs[0](obj) << std::endl;
}
private:
std::vector<std::function<int(Thing*)>> myfuncs; 
};

class Thing: public OtherThing{
public:
Thing(){
    std::function<int(Thing*)> myfunc= [](Thing* obj)->int{
        std::cout << "from lambda " << obj->value << std::endl;
        return obj->value;
        };
    this->addElement(myfunc);
    }
void setValue(int value){
    this->value = value;
}
int getValue(){
    return this->value;
}
private:
int value;
};


int main() {
    // container for things 
    std::vector<Thing> mythings;
    
    // a thing
    Thing a;
    
    
    // copy is here
    mythings.push_back(a);
    
    // test
    mythings[0].setValue(666);
    mythings[0].toggle(&mythings[0]);
    mythings[0].setValue(999);
    mythings[0].toggle(&mythings[0]);

    return 0;
}

产出:

代码语言:javascript
复制
toggle .. from lambda 666
666
toggle .. from lambda 999
999
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69510628

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档