如何让C++中第二个Vector存储原对象引用以同步修改原对象?
问题描述
我正在把Java代码里的性能关键部分转成C++。Java里往第二个List添加原List的对象时只存储引用,修改子List里的对象会同步影响原List的对应对象;但C里用push_back往子Vector添加对象会执行深拷贝,导致修改子Vector的对象无法影响原Vector的对象。以下是Java和C的示例代码,请问如何修改C++代码使其输出为true?
Java示例代码
class Data { Data(int id){ this.id = id; this.name = "Name " + id; } public int id; public String name = ""; public boolean isFancy = false; } public class Main { public static void main(String[] args) { List<Data> dataList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Data data = new Data(i); dataList.add(data); } List<Data> dataSublist = new ArrayList<>(); dataSublist.add(dataList.get(2)); dataSublist.add(dataList.get(3)); dataSublist.add(dataList.get(8)); dataSublist.forEach(data -> data.isFancy = true); // 修改子List中的对象会同步影响原对象 System.out.println("Data 3 original isFancy = " + dataList.get(3).isFancy); // 输出true } }
原C++示例代码(输出false)
class Data { public: Data(int id) { id_ = id; }; int id_ = 0; std::string name_ = ""; bool isFancy_ = false; }; int main() { std::vector<Data> dataList; for (int i = 0; i < 10; i++) { Data data = Data(i); dataList.push_back(data); } std::vector<Data> dataSublist; dataSublist.push_back(dataList[2]); dataSublist.push_back(dataList[3]); dataSublist.push_back(dataList[8]); for (int i = 0; i < dataSublist.size(); i++) { dataSublist[i].isFancy_ = true; // 修改子Vector的对象不会影响原对象 } std::cout << "Data 3 original isFancy = " << ((dataList[3].isFancy_) ? "true" : "false"); // 输出false }
解决方案
要让C++实现Java式的对象引用共享,核心是让子Vector存储原对象的引用或指针,而非对象副本。以下是几种可行方案:
方案1:使用智能指针(推荐,安全无内存泄漏)
用std::shared_ptr自动管理对象内存,同时实现多容器共享同一对象。
#include <vector> #include <iostream> #include <string> #include <memory> class Data { public: Data(int id) : id_(id), name_("Name " + std::to_string(id)) {}; int id_ = 0; std::string name_ = ""; bool isFancy_ = false; }; int main() { std::vector<std::shared_ptr<Data>> dataList; // 直接创建智能指针并加入容器,避免拷贝 for (int i = 0; i < 10; i++) { dataList.push_back(std::make_shared<Data>(i)); } std::vector<std::shared_ptr<Data>> dataSublist; // 存储原容器中对象的智能指针,共享同一对象 dataSublist.push_back(dataList[2]); dataSublist.push_back(dataList[3]); dataSublist.push_back(dataList[8]); // 修改子容器中的指针指向的对象,直接作用于原对象 for (auto& dataPtr : dataSublist) { dataPtr->isFancy_ = true; } std::cout << "Data 3 original isFancy = " << ((dataList[3]->isFancy_) ? "true" : "false") << std::endl; // 输出true,无需手动释放内存,智能指针会自动处理 }
方案2:使用原始指针(性能最优,需手动管理内存)
如果追求极致性能且能确保内存安全,可以使用原始指针,但要注意手动释放内存避免泄漏。
#include <vector> #include <iostream> #include <string> class Data { public: Data(int id) : id_(id), name_("Name " + std::to_string(id)) {}; int id_ = 0; std::string name_ = ""; bool isFancy_ = false; }; int main() { std::vector<Data*> dataList; // 动态分配对象,存储指针 for (int i = 0; i < 10; i++) { dataList.push_back(new Data(i)); } std::vector<Data*> dataSublist; dataSublist.push_back(dataList[2]); dataSublist.push_back(dataList[3]); dataSublist.push_back(dataList[8]); for (auto dataPtr : dataSublist) { dataPtr->isFancy_ = true; } std::cout << "Data 3 original isFancy = " << ((dataList[3]->isFancy_) ? "true" : "false") << std::endl; // 手动释放所有动态分配的内存 for (auto dataPtr : dataList) { delete dataPtr; } }
方案3:使用引用包装器(无指针,C++11及以上)
用std::reference_wrapper将对象引用包装为可拷贝类型,存储在Vector中,既避免拷贝又无需管理内存。
#include <vector> #include <iostream> #include <string> #include <functional> // 包含std::reference_wrapper class Data { public: Data(int id) : id_(id), name_("Name " + std::to_string(id)) {}; int id_ = 0; std::string name_ = ""; bool isFancy_ = false; }; int main() { std::vector<Data> dataList; // 直接在容器内构造对象,避免拷贝 for (int i = 0; i < 10; i++) { dataList.emplace_back(i); } std::vector<std::reference_wrapper<Data>> dataSublist; // 存储原对象的引用包装 dataSublist.push_back(dataList[2]); dataSublist.push_back(dataList[3]); dataSublist.push_back(dataList[8]); // 通过get()获取原对象引用并修改 for (auto& dataRef : dataSublist) { dataRef.get().isFancy_ = true; } std::cout << "Data 3 original isFancy = " << ((dataList[3].isFancy_) ? "true" : "false") << std::endl; }
内容的提问来源于stack exchange,提问作者Gunnar Bernstein
相关产品推荐
相关产品推荐

