如何正确创建带Access类的多个Entity类对象?
问题分析与解决方案
问题根源
使用std::vector<Entity> versionVec(2, 4);创建多个对象时,vector会先构造一个临时Entity(4)对象,再通过拷贝构造生成vector中的两个元素。但Access类的_vec是引用类型,拷贝构造时引用不会自动重新绑定到新对象的_data,而是仍然指向临时对象的_data——临时对象在vector构造完成后就会销毁,导致accessName中的引用变成悬垂引用,后续操作自然无法修改目标对象的_data。
正确创建方式
方式1:直接在vector内构造对象(推荐)
使用emplace_back在vector的内存空间中直接构造每个Entity,避免拷贝操作:
std::vector<Entity> versionVec; // 直接在vector中构造两个Entity对象 versionVec.emplace_back(4); versionVec.emplace_back(4); // 此时操作会正常生效 versionVec[0].accessName[0] = 1; for (const auto &e : versionVec[0]._data) { std::cout << e << ", "; } std::cout << "\n";
这种方式下,每个Entity的accessName引用会直接绑定到自身的_data,不会出现悬垂问题。
方式2:修改Access类为指针类型
将Access中的引用成员改为指针,这样拷贝构造时可以重新初始化指针指向当前对象的_data:
#include <iostream> #include <vector> class Access{ public: // 改用指针初始化 Access(std::vector<double>* data) : _vec(data) {} double& operator[](size_t i) { return (*_vec)[i]; } private: std::vector<double>* _vec; }; class Entity { public: Entity(size_t n) : _data(n), accessName(&_data) {} // 显式拷贝构造函数,初始化Access指向当前对象的_data Entity(const Entity& other) : _data(other._data), accessName(&_data) {} // 拷贝赋值函数 Entity& operator=(const Entity& other) { if (this != &other) { _data = other._data; } return *this; } std::vector<double> _data; Access accessName; }; // 现在原创建方式可以正常工作 int main() { std::vector<Entity> versionVec(2, 4); versionVec[0].accessName[0] = 1; for (const auto &e : versionVec[0]._data) { std::cout << e << ", "; } std::cout << "\n"; return 0; }
方式3:禁用拷贝,使用移动语义
如果不需要拷贝Entity,可以删除拷贝构造/赋值函数,提供移动构造函数确保引用正确绑定:
class Entity { public: Entity(size_t n) : _data(n), accessName(_data) {} // 删除拷贝构造与赋值 Entity(const Entity&) = delete; Entity& operator=(const Entity&) = delete; // 移动构造函数,重新绑定Access到当前对象的_data Entity(Entity&& other) noexcept : _data(std::move(other._data)), accessName(_data) {} // 移动赋值函数(若需要) Entity& operator=(Entity&& other) noexcept { if (this != &other) { _data = std::move(other._data); // 注意:引用无法重新绑定,若需移动赋值,建议将Access改为指针类型 } return *this; } std::vector<double> _data; Access accessName; }; // 创建方式 std::vector<Entity> versionVec; versionVec.push_back(Entity(4)); versionVec.push_back(Entity(4));
内容的提问来源于stack exchange,提问作者PyOPTProblem
相关产品推荐
相关产品推荐

