C++跨类实例修改成员变量:引用解决拷贝无效修改问题
解决C++中跨实例修改成员变量的拷贝问题
你遇到的核心问题非常清晰:你的vector存储的是对象的副本,而非原对象的引用或指针。所以无论你怎么修改vector里的对象,都是在操作拷贝出来的新对象,和原实例完全没有关联。接下来我会一步步帮你调整代码,实现你想要的修改同步效果。
问题根源拆解
- 调用
Andy.setList(John)时,setList的参数是传值方式,这会把John完整复制一份后放进Andy的list里; - 调用
getList()时,又会把整个vector复制一份返回给list_of_Andy,这额外多了一层拷贝; - 最后修改
list_of_Andy里的对象,自然和原John实例毫无关系。
解决方案:用指针存储对象引用
因为C++的vector不能直接存储引用(引用不可重新绑定的特性不符合vector元素的可赋值要求),所以我们用指针来存储原对象的地址,这样操作的就是原实例本身。
修改后的完整代码
classes.h
#include<string> #include<iostream> #include<vector> class Man; class Woman; class Man { public: Man(); std::string name; // 将vector改为存储指针类型 std::vector<Woman*> list; void setName(std::string nameIn); std::string getName(); // 参数改为指针类型,直接传入原对象地址 void setList(Woman* womanIn); // 返回vector的引用,避免拷贝整个容器 std::vector<Woman*>& getList(); }; class Woman { public: Woman(); std::string name; // 将vector改为存储指针类型 std::vector<Man*> list; void setName(std::string nameIn); std::string getName(); // 参数改为指针类型,直接传入原对象地址 void setList(Man* manIn); // 返回vector的引用,避免拷贝整个容器 std::vector<Man*>& getList(); }; // 类实现部分 Woman::Woman() { name = "undeclared"; } void Woman::setName(std::string nameIn) { name = nameIn; } std::string Woman::getName() { return name; } void Woman::setList(Man* manIn) { list.push_back(manIn); } std::vector<Man*>& Woman::getList() { return list; } Man::Man() { name = "undeclared"; } void Man::setName(std::string nameIn) { name = nameIn; } std::string Man::getName() { return name; } void Man::setList(Woman* womanIn) { list.push_back(womanIn); } std::vector<Woman*>& Man::getList() { return list; }
main.cpp
#include "classes.h" int main() { Woman Andy; Man John; Andy.setName("Andy"); John.setName("John"); // 传入对象的地址,而非对象本身 Andy.setList(&John); John.setList(&Andy); // 接收vector的引用,避免拷贝容器 std::vector<Man*>& list_of_Andy = Andy.getList(); std::vector<Woman*>& list_of_John = John.getList(); // 用->访问指针指向的对象成员 std::cout << "name of persons in the lists " << list_of_Andy.at(0)->getName() << " " << list_of_John.at(0)->getName() << std::endl; std::cout << "name of persons " << Andy.getName() << " " << John.getName() << std::endl; // 修改指针指向的原对象 list_of_Andy.at(0)->setName("JohnWick"); list_of_John.at(0)->setName("AndySugars"); std::cout << "name of persons in the lists " << list_of_Andy.at(0)->getName() << " " << list_of_John.at(0)->getName() << std::endl; std::cout << "name of persons " << Andy.getName() << " " << John.getName() << std::endl; int a; std::cin >> a; return 0; }
代码修改说明
- vector类型调整:把
std::vector<Man>改成std::vector<Man*>,这样容器存储的是原对象的地址,而非拷贝; - setList参数优化:从传值改成传指针,直接将原对象的地址存入vector,避免对象拷贝;
- getList返回引用:用
std::vector<Man*>&返回容器的引用,既避免返回时拷贝整个vector,又保证操作的是原容器里的指针; - 访问方式变更:用
->代替.来访问指针指向的对象的成员函数或变量。
更安全的进阶选择:智能指针
如果担心原始指针的生命周期问题(比如原对象被销毁后指针变成悬空指针),可以用std::shared_ptr来自动管理内存:
- 将vector类型改为
std::vector<std::shared_ptr<Man>>; - 创建对象时用
std::make_shared<Man>(); - 传入时直接传递shared_ptr即可,不需要取地址。
这种方式可以自动维护对象的生命周期,彻底避免悬空指针风险。
运行修改后的代码,你会发现修改vector里的对象时,原实例的name会同步改变,输出完全符合你的预期。
内容的提问来源于stack exchange,提问作者Saba
相关产品推荐
相关产品推荐

