C++ new运算符
一、new运算符初始化
C++ 98 如何初始化动态分配的变量?
如果为内置的标准类型分配存储空间并初始化,可在类型名后面加上初始值,并将其用括号括起,如下:
int *pi = new int(10); // pi初始化设置成10
double *pd = new double(99.99); // pd初始化设置成99.99
这种括号语法也可用于有合适构造函数的类。
C++11 增加初始化动态分配变量的初始化方式:
初始化常规结构或数组,使用大括号列表初始化方式,如下:
struct where
{
double x;
double y;
double z;
};
where *one = new where { 2.5, 5.3, 7.2};
int *ar = new int[4] {2, 4, 6 ,8};
还可将列表用于单值变量初始化,如下:
int *pin = new int {6};
double *pdo = new double {99.99};
二、new失败
new可能找不到请求的内存量。C++刚开始的10年时,是让new返回空指针;但现在将引发异常std::bad_alloc。(后期再详细描述)
三、new:运算符、函数与替换函数
(1)运算符new和new[]分别调用如下函数,这些函数被称为分配函数,它们位于全局名称空间中:
void* operator new(std::size_t); // 用于new
void* operator new[](std::size_t); // 用于new[]
举例说明new运算符使用时调用的new()函数,如下:
// 第一种
int *pi = new int;
// 实际转换为:
int *pi = new(sizeof(int));
// 第二种
int *pa = new int[40];
// 实际转换为:
int *pa = new(40 * sizeof(int));
(2)运算符delete和delete[]则分别调用如下函数:
void operator delete(void *);
void operator delete[](void *);
举例说明delete运算符使用时调用的delete()函数,如下:
delete pi;
// 实际转换为
delete(pi);
四、定位new运算符
简介:
new运算符另一种使用: 被称为定位new运算符,它让程序员指定要使用的位置。程序员可以使用这种特性来设置其内存管理规程、处理需要通过特定地址访问的硬件或在特定位置创建对象。
使用方式:
(1)首先包含头文件,它提供了这种版本的new运算符的原型
(2)然后将new运算符用于提供了所需地址的参数。除需要指定参数外,句法与常规new运算符相同
具体使用方式如下述代码所示:
#include <new>
struct chaff
{
char dross[20];
int slag;
};
char buffer1[50];
char buffer2[500];
void test()
{
chaff *p1;
int *p2;
p1 = new (buffer1) chaff;
p2 = new (buffer2) int[20];
}
上述代码中的定位new运算符从buffer1中分配空间给了结构体chaff,从buffer2中分配空间给了一个包20个元素的int数组。
扩展:
定位new运算符的另一种用法: 将其与初始化结合使用,从而将信息放在特定的硬件地址处。
定位new运算符工作原理: 基本上它只是返回传递给它的地址,并将其强制转换为 (void *),以便能够赋给任何指针类型。这里说的是默认定位new函数,C++允许程序员重载定位new函数。
定位new函数: 定位new函数不可替换,但可重载。
举例说明定位new运算符使用时调用的new()函数,它是调用一个接收两个参数的new()函数,如下:
int *pi = new int; // 调用 new(sizeof(int))
int *p2 = new (buffer) int; // 调用 new(sizeof(int), buffer)
int *p3 = new (buffer) int[40]; // 调用 new(40 * sizeof(int), buffer)