new
-
内存分配与对象初始化:
new
是一个操作符,它不仅负责在堆(heap)上分配内存,而且还能负责调用构造函数来初始化对象。- 对于内置类型(如int、float等),
new
只分配内存,不执行任何构造函数。 - 对于类类型的对象,
new
会分配内存,并自动调用相应的构造函数来初始化分配的内存。
-
返回值:
new
返回指向分配内存的指针,指针类型与所分配对象的类型匹配。
-
错误处理:
- 如果
new
无法分配所需的内存,它会抛出std::bad_alloc
异常,而不是返回NULL
。
- 如果
-
语法:
new
的基本用法如下:int* ptr = new int; // 分配一个int类型的内存,并默认初始化为0 int* ptr = new int(1); //分配一个int类型的内存,并初始化为1 MyClass* obj = new MyClass(); // 分配一个MyClass类型的内存,并调用构造函数 MyClass* obj = new MyClass(1);//分配一个MyClass类型的内存,并把1传给构造函数并构造 MyClass* obj = new MyClass(1,2);//构造函数有多个参数 MyClass* A(1, 1); MyClass* obj = new MyClass(A);//调用拷贝构造
delete
-
释放内存与对象析构:
delete
是与new
对应的操作符,用于释放由new
分配的内存。- 对于类类型的对象,
delete
会调用析构函数来销毁对象,然后释放内存。 - 对于内置类型的指针,
delete
只释放内存,不调用任何析构函数。
-
语法:
delete
的基本用法如下:delete ptr; // 释放ptr指向的int类型的内存 delete obj; // 调用obj指向的MyClass对象的析构函数,并释放内存
-
注意事项:
- 使用
delete
时,必须确保它是new
分配的内存,否则可能会引起未定义行为。 - 如果一个指针指向一个数组,则需要使用
delete[]
来释放整个数组的内存,而不是delete
。
- 使用
new[] 和 delete[]
- 当需要动态分配数组时,C++ 提供了
new[]
和delete[]
操作符。 new[]
用于分配一个数组的内存,并调用每个元素的构造函数(如果是类类型)。delete[]
用于释放整个数组的内存,并调用每个元素的析构函数(如果是类类型)。
new 和 delete 与 malloc 和 free 的区别
-
类型安全性:
new
和delete
是类型安全的,因为它们知道正在操作的对象类型。malloc
和free
是类型无关的,程序员需要手动管理类型信息和内存的初始化与销毁。
-
异常处理:
new
可以抛出异常来处理内存分配失败的情况,而malloc
在失败时返回NULL
。
-
初始化与析构:
new- 自动处理对象的构造和析构过程,而
malloc和
free不涉及对象的构造和析构。这意味着使用
new和
delete` 时,不需要手动调用构造函数和析构函数。
示例
下面是使用 new
和 delete
分配和释放单个对象以及数组的示例:
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "构造." << std::endl; }
~MyClass() { std::cout << "析构" << std::endl; }
};
int main() {
// 分配单个对象
MyClass* obj = new MyClass();
// ...
delete obj; // 释放单个对象
// 分配对象数组
MyClass* array = new MyClass[5];
// ...
delete[] array; // 释放对象数组
return 0;
}
在这个例子中,使用 new
分配了一个 MyClass
类型的对象和一个 MyClass
类型的数组。之后,使用 delete
和 delete[]
分别释放了这些对象。
注意事项
- 当使用
delete
删除一个指针时,应确保该指针不为空,且之前确实使用了new
来分配内存。 - 如果对同一个内存地址使用多次
delete
,将导致未定义行为,可能导致程序崩溃。 - 应避免对
NULL
指针使用delete
,尽管这不会引起程序崩溃,但它是多余的。 - 对于指向数组的指针,必须使用
delete[]
而不是delete
,否则只会析构数组的第一个元素,而不会释放整个数组占用的内存。