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

无法访问vector<vector<?>>元素,求二维向量赋值正确方法

问题描述

我定义了如下类,其唯一成员为vector<vector<struct Pixel>>:

struct Pixel {
    float r, g, b;
};

class Test {
private:
  vector<vector<struct Pixel>> pixels;
public:
  void read(std::string filename);
};

在read方法中,我先从文件读取数据存入一维vector:

std::vector<pixel> v;

while(getline(file, line_pixels)) {
  if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
    std::stringstream ss(line_pixels);
    std::string value;
    while(getline(ss, value, ' ')) {
      pixel p;
      p.r = p.g = p.b = stoi(value);
      v.emplace_back(p);
    }
  }
}

之后尝试将一维vector的数据转存到二维vectorpixels,两种实现方式均出现段错误:

第一种方式,访问pixels元素时触发段错误:

int index = 0;
size_t h = stoi(height), w = stoi(width);
for(size_t i=0; i<h; i++) {
  std::vector<pixel> row;
  for(size_t j=0; j<w; j++)
    row.push_back(v[index++]);
  pixels.push_back(row);
}

第二种方式,执行resize语句时触发段错误:

size_t h = stoi(height), w = stoi(width);
pixels.resize(h);
for(size_t i=0; i<h; i++)
  pixels[i].resize(w);
for(size_t i=0; i<v.size(); i++) {
  int row = i / w;
  int col = i % w;
  pixels[row][col] = v[i];
}

请问正确的实现方式是什么?

更新
完整代码分为两个项目:一个包含实现read方法的Netpbm和Bitmap类,另一个项目调用前者的方法。


问题分析与正确实现

段错误的核心原因集中在这几点:

  1. 类型不匹配:代码混用大小写不一致的Pixel和pixel,C++强类型特性会导致未定义行为。
  2. 尺寸有效性缺失:stoi(height)/stoi(width)可能得到负数、超大值等无效数据,或一维vectorv的元素总数不等于h*w,引发越界访问。
  3. 读取逻辑隐患:文件读取的像素数量与预期尺寸不匹配,后续操作触发越界。

修正后的实现步骤

1. 统一类型命名

将所有pixel改为Pixel,同时注意把int类型的像素值转为float(匹配Pixel成员类型):

// 修正一维vector的类型
std::vector<Pixel> v;

while(getline(file, line_pixels)) {
  if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
    std::stringstream ss(line_pixels);
    std::string value;
    while(getline(ss, value, ' ')) {
      Pixel p;
      // 显式转换为float,避免隐式转换问题
      p.r = p.g = p.b = static_cast<float>(stoi(value));
      v.emplace_back(p);
    }
  }
}

2. 校验尺寸与像素数量合法性

转换前先确认尺寸有效,且像素总数匹配,从根源避免越界:

// 转换并校验height、width
int h_int = stoi(height);
int w_int = stoi(width);
if (h_int <= 0 || w_int <= 0) {
    throw std::invalid_argument("无效的图像尺寸");
}
size_t h = static_cast<size_t>(h_int);
size_t w = static_cast<size_t>(w_int);

// 校验像素总数与尺寸是否匹配
if (v.size() != h * w) {
    throw std::runtime_error("像素数量与图像尺寸不匹配");
}

3. 安全转换为二维vector(推荐优化后的第二种方式)

// 清空原有数据,避免残留干扰
pixels.clear();
// 初始化二维vector的行
pixels.resize(h);
for (size_t i = 0; i < h; ++i) {
    // 初始化每行的列数
    pixels[i].resize(w);
}

// 填充数据(已校验过总数,不会越界)
for (size_t i = 0; i < v.size(); ++i) {
    size_t row = i / w;
    size_t col = i % w;
    pixels[row][col] = v[i];
}

也可以用优化后的第一种方式:

pixels.clear();
size_t index = 0;
for (size_t i = 0; i < h; ++i) {
    std::vector<Pixel> row;
    row.reserve(w); // 提前预留空间,提升效率
    for (size_t j = 0; j < w; ++j) {
        row.push_back(v[index++]);
    }
    pixels.push_back(row);
}

额外注意事项

  • 确保文件已正确打开,否则getline会失败导致v为空,后续操作必然出错。
  • 若height/width是从文件读取的字符串,建议先做trim处理,避免多余空白字符导致stoi抛出异常。

内容的提问来源于stack exchange,提问作者Kleber Mota

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 22:01:16