C++内存重分配时指针引用的用法及相关编译错误求解
关于C++指针引用与动态内存重分配的问题
问题1:编译错误的原因是什么?
你遇到的编译错误invalid initialization of non-const reference of type 'char*&' from an rvalue of type 'char*',核心原因是数组退化为指针时产生的是右值,无法绑定到非常量左值引用:
- 当你在
main里调用Mystrcat(str0, ", World!")时,str0是栈上的char[100]数组,传递给函数参数时会自动退化为char*类型的临时右值(这个临时指针指向数组首地址,但本身是不可修改的临时值)。 - 而函数参数
char* &des是非常量左值引用,C++规定非常量左值引用只能绑定到可被修改的左值(比如明确的char*变量),不能绑定右值,因此编译报错。
你误以为char* &des = str0合法,但这句代码本身也会编译失败——str0是数组名,不是char*类型变量,数组名可隐式转换为char*右值,但同样无法绑定到非常量左值引用。
另外要注意:你试图通过修改des重新分配内存的逻辑,本身和栈数组不兼容。栈上数组的内存是编译期固定分配的,地址不可改变,即使编译通过,把des改成new出来的堆地址,也不会改变原栈数组str0的内存,反而会造成内存泄漏。
问题2:如何在内存重分配时使用指针引用?
指针引用的作用是让函数能修改传入的指针变量本身(比如改变指针指向的地址),但使用前提是:传入的必须是可修改的char*类型左值(即动态分配的指针变量),而非栈上的数组。
修正后的完整代码
#include <iostream> #include <cstring> // 实现自定义字符串长度函数 unsigned int Mystrlen(const char* str) { unsigned int len = 0; while (str[len] != '\0') { len++; } return len; } void Mystrcat(char* &des, const char* src) { unsigned int des_len = Mystrlen(des); unsigned int src_len = Mystrlen(src); char* temp_str = des; // 分配足够容纳拼接后字符串的新内存 des = new char[des_len + src_len + 1]; // 复制原字符串内容 for(unsigned int i = 0; i < des_len; i++) { des[i] = temp_str[i]; } // 拼接源字符串内容 for(unsigned int i = 0; i < src_len; i++) { des[des_len + i] = src[i]; } // 添加字符串结束符,避免乱码 des[des_len + src_len] = '\0'; // 释放原内存,防止泄漏 delete[] temp_str; } int main() { // 使用动态分配的指针,替代栈数组 char* str0 = new char[100]; std::strcpy(str0, "Hello"); Mystrcat(str0, ", World!"); std::cout << str0 << std::endl; // 输出"Hello, World!" // 释放动态分配的内存 delete[] str0; return 0; }
关键要点说明:
- 用动态指针替代栈数组:栈数组地址固定,无法通过指针引用修改指向;只有动态分配的
char*变量,才能通过引用修改其指向,让它指向重新分配的堆内存。 - 释放原内存:分配新内存后必须释放原
temp_str指向的内存,避免内存泄漏。 - 补充字符串结束符:原代码未添加
'\0',会导致输出乱码,必须手动添加字符串结束标记。 - 类型匹配:
Mystrlen返回unsigned int,循环变量建议同步使用该类型,避免类型不匹配警告。
你之前提到用char* des作为参数时无法获取数组总大小——这是因为数组退化为指针后,sizeof(des)只能得到指针本身的大小(如4或8字节),无法获取原数组长度。如果要处理栈数组的拼接,需要额外传递数组总容量参数,但这种情况下无法修改数组内存(栈数组容量固定),只能在原有容量内完成拼接。
内容的提问来源于stack exchange,提问作者ragedhumancompiler
相关产品推荐
相关产品推荐

