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

为何STL array首元素为数组大小,其副本却符合预期?

问题分析与解答

问题描述

我原本想学习如何将一维数组当作二维数组进行旋转,却发现了异常现象:声明包含16个int的std::array,打印时首元素显示为16(数组大小),但复制到同大小的std::array后,副本打印结果符合初始定义值。后续发现复制代码存在数组越界错误,但仍有疑问:为何原数组首元素变为数组大小,副本却无此问题?

相关代码:

// 打印函数
void func(std::array<int, 16> arr){
   for(int i = 0; i < 16; ++i){    
      std::cout << arr[i] << ' ';
      if((i + 1) % 4 == 0) 
         std::cout << std::endl;
   }
}
// 原数组声明
std::array<int, 16> arr{
   1, 2, 3, 4,
   0, 1, 2, 3, 
   0, 0, 1, 2,
   0, 0, 0, 1
};
// 复制代码(存在越界)
for(int i = 0; i <= 16;++i){
   rotd_arr[i] = arr[i];
}

核心原因:数组越界触发的未定义行为

你的问题本质是数组越界访问导致的未定义行为,具体现象和编译器的内存布局直接相关,拆解如下:

  • 越界访问的发生
    复制循环的条件是i <= 16,会执行17次循环(i从0到16),但std::array<int,16>的有效索引范围是0~15。当i=16时,arr[16]属于越界读取,rotd_arr[16]属于越界写入——这在C++中是未定义行为,编译器无法保证任何预期结果。

  • 原数组首元素变为16的具体原因
    在你的编译环境中,rotd_arr和arr的栈内存可能相邻。执行rotd_arr[16] = arr[16]时:

    1. arr[16]越界读取到栈上的循环变量i的当前值16;
    2. rotd_arr[16]的内存地址恰好覆盖了arr的首元素arr[0]的地址,导致arr[0]被意外修改为16。
  • 副本打印正常的原因
    副本rotd_arr的有效元素是索引0~15,越界写入的rotd_arr[16]不在打印函数的遍历范围内,因此有效元素未被破坏,打印结果看起来符合初始值。但实际上rotd_arr的内存已经被非法修改,只是影响的是数组之外的区域。

修复方案

将循环条件改为i < 16,确保只访问有效索引:

for(int i = 0; i < 16; ++i){
   rotd_arr[i] = arr[i];
}

或者直接使用std::array的赋值运算符,更简洁安全:

rotd_arr = arr;

内容的提问来源于stack exchange,提问作者Noah M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:37:22