直接通过下标赋值是最常用方式;需防范越界写入和修改字符串字面量两类高发错误,前者导致内存破坏,后者引发段错误或未定义行为。

直接通过下标赋值是最常用方式
数组元素修改的本质就是对内存中某个位置重新写入数据,C++ 里最直接的手段就是用方括号 [] 加索引。只要索引在合法范围内(0 到 size-1),就能安全修改。
常见错误是越界写入:比如声明 int arr[5],却执行 arr[5] = 10 —— 这会改写相邻内存,可能不报错但行为不可预测,甚至导致后续 malloc 失败或程序崩溃。
- 静态数组:直接
arr[i] = new_value,注意i必须 - 动态数组(
new int[n]):同样用ptr[i] = new_value,但需确保i - 用
std::vector更安全:vec[i] = new_value不检查边界,vec.at(i) = new_value会抛std::out_of_range
用指针遍历修改时要注意生命周期
把数组名当指针用(如 int* p = arr)再通过 *(p + i) 修改,逻辑上等价于下标访问,但更容易出问题——尤其当原数组是局部变量、函数返回后指针就悬空了。
典型陷阱:函数内创建数组并返回其首地址,调用方拿到指针后修改,实际改的是已释放栈空间。
立即学习“C++免费学习笔记(深入)”;
- 确认数组存储期:全局/静态数组、堆分配(
new)、或传入的参数(如void func(int arr[], size_t n))才可安全用指针修改 - 避免
return arr;这类操作;若必须返回,改用std::vector或智能指针管理 -
const int* p不能用于修改;要改就得是int* p或非 const 引用
批量修改建议用 std::fill 或 std::for_each
单个赋值写多了易错且啰嗦,标准库提供了更清晰、不易越界的替代方案。
std::fill 适合全数组设为同一值,std::for_each 配合 lambda 可实现条件更新(比如只改偶数索引位置),且自动处理迭代器范围,不依赖手动算长度。
- 填充值:
std::fill(std::begin(arr), std::end(arr), 42) - 条件修改:
std::for_each(std::begin(vec), std::end(vec), [](int& x) { if (x > 10) x *= 2; }); - 注意
std::begin/std::end对原生数组有效,但对指针无效(如int* p)——此时必须显式传长度
修改字符串字面量会触发未定义行为
这是一类高发、隐蔽的错误:写 char* s = "hello"; s[0] = 'H'; 看似合理,实则非法。字符串字面量存储在只读段,运行时修改会导致段错误(Linux/macOS)或静默失败(某些 Windows 环境)。
正确做法是用字符数组初始化:char s[] = "hello";,这样内容存在栈上,可读写。
- 编译器通常不报错,但启用
-Wwrite-strings(GCC/Clang)能警告const char*赋值给char* -
std::string安全得多:std::string s = "hello"; s[0] = 'H';没问题 - 如果必须用 C 风格字符串且需修改,用
strdup("hello")或new char[6]手动复制
直接改下标最快,但越界和字符串字面量这两处最容易被忽略,一跑就崩,一查就半天。


















