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

如何正确创建带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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:52:43