C++ new关键字详解

一.new的基本用法

1.c++通过new关键字进行动态分配内存。

2.new开辟的空间存储在堆上,而我们定义的变量存储在栈上。

3.new分配的空间使用delete释放,new[] 使用 delete[]。

4.

int* pi = new int(5);//表示动态分配一个int ,初始化为 5
int* pa = new int[5];//表示动态分配一个数组,数组大小为5

二.new和malloc的区别

1.malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。 由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

3.new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换;malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。

4.new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。

5.使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算;malloc则需要显式地指出所需内存的尺寸。

三.应用

1.new operator

就是我们平常用的new

new operator实际上执行了以下几个步骤:

①调用operator new分配内存。

如果类本身未定义operator new,那么会调用全局的operator new。

// 全局 operator new
void * operator new(std::size_t size) throw(std::bad_alloc)
{
    if (size == 0)
    {    
        size = 1;
    }
    void* p;
    while ((p = ::malloc(size)) == 0) 
    { //采用 malloc 分配空间
        std::new_handler nh = std::get_new_handler();
        if (nh)
            nh();
        else
            throw std::bad_alloc();
    }
    return p;
}

每个类可以重载operator new(),如果类自己定义了operator new(),则调用自己的定义的 operator new,而不是全局的。

通过定义可以发现operator new()只是分配了内存空间。

②.调用构造函数,将配置得来的对象设立初值。

2.operator new

函数operator new 通常声明如下:

void * operator new(size_t size);

其返回值类型是void * ,返回一个指针,指向一块原始的、未设初值的内存,函数中size_t参数表示需要分配多少内存。你可以重载operator new,加上额外的参数,但参数第一个类型必须是size_t。

例子:

void *rawMemory = operator new(sizeof(string))

这里的operator new将返回指针,指向一块足够容纳一个string对象的内存。和malloc一样,operator new唯一任务就是分配内存。

3.placement new

有时候你真的会想直接调用一个构造函数,偶尔会有一些分配好的原始内存,你需要在上面构建对象。有一个特殊版本的operator new,称为 placement new。

例子:

class Widget
{
public:
    Widget(int widgetSize);
...
};

Widget *constructWidgetInBuffer(void *buffer,int widgetSize)
{
    return new (buffer) Widget(widgetSize);
}

此函数返回指针,指向一个Widget 对象,它被构造于传递此函数的一块内存缓冲区上。其中指定一个自变量(buffer)作为new operator "隐式调用 operator new"时所用。于是,被调用的operator new 除了接受 "一定得有的size_t自变量" 之外,还接受了一个 void* 参数,指向一块内存,准备用来接受构造好的对象。这样的operator new 称为 placement new,看起来像这样:

void *operator new(size_t,void *location)
{
    return location;
}

前面已经说了 operator new的目的是为对象找到一块内存,然后返回一个指针指向它。在placement new的情况下,调用者已经知道指向内存的指针了,placement new唯一需要做的就是将它获得的指针再返回。想要使用placement new 必须#include<new>

4.总结

1.如果你希望将对象产生于堆上,请使用new operator。

2.如果你只打算分配内存,请使用operator new,就不会调用构造函数。

3.如果你打算在堆对象产生时自己决定内存分配方式,请自己重载operator new。

4.如果你打算在已分配的内存中构造对象,请使用placement new。

猜你喜欢

转载自blog.csdn.net/wzz953200463/article/details/103586435