new 运算符

在 C++ 中,动态内存分配使用 new 运算符。它会在堆(heap)上分配指定大小的内存,并返回指向该内存首地址的指针。分配的对象(或数组)会存活到被 delete 释放为止,而不会因离开作用域自动销毁。

核心用法:new 与 new[]

  • new char:分配一个字符大小的内存,返回 char*
  • new char[size]:分配 size 个字符的连续内存块(数组),返回 char*(指向第一个元素)。
  • 注意:如果分配的是数组,则必须使用 new[] 形式,后续释放必须对应 delete[]

在构造函数中的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyString {
public:
MyString(const char* s) {
// 1. 计算字符串长度
int len = strlen(s);
// 2. 用 new[] 分配堆内存
str = new char[len + 1]; // +1 留给 '\0'
// 3. 拷贝内容
strcpy(str, s);
}
private:
char* str;
};

为什么需要区分 newnew[]?这关系到内存布局的底层机制。编译器在分配数组时,会在块头部额外存储元素个数等信息。若使用 delete 释放 new[] 创建的内存,行为是未定义的。new 必须与 delete 配对,new[] 必须与 delete[] 配对。

delete 运算符

new 对应,delete 运算符用于释放之前通过 new 分配的堆内存。释放后,内存被归还给操作系统,但指针变量本身仍然存在,指向一个无效的地址——这就是悬空指针。

在析构函数中的使用

1
2
3
4
5
6
7
8
9
10
11
class MyString {
public:
~MyString() {
// 释放堆内存
delete[] str;
// 置空指针,避免悬空
str = nullptr;
}
private:
char* str;
};

C 风格字符串

C 风格字符串是以 '\0'(空字符)结尾的字符数组。处理这类字符串时,必须依赖 strlenstrcpy 等标准库函数,它们都依赖于 '\0' 来定位字符串的结束位置。

image

strlen 示例

1
2
char str[] = "hello";
int len = strlen(str); // len = 5

strcpy 示例

1
2
3
char src[] = "world";
char dst[10];
strcpy(dst, src); // dst = "world"

内存分配不足:使用 new char[len] 时,必须分配 len + 1 个字节(为 ‘\0’ 留出空间)。如果只分配 len 个字节,strcpy 会越界写入,导致内存损坏