-
new和delete
2016-01-18 14:34:57new和deletenew和delete的使用
变量申请与释放
Type* pointer = new Type;
delete pointer;
例:
int* p = new int;
delete p;
也可以直接初始变量,如下
int *p = new int(1);
delete p;数组的申请
Type* pointer = new Tpye[N];
delete[] pointer;//注意要加[],不然会当做P指向一个变量只指向一个变量,那么只释放一个变量。 -
new 和 delete
2014-12-10 19:22:06new 和 delete能够动态的创建数组,删除数组。 char *a = new char; delete a; char *a = new char[12] //创建一个12个字节的字符数组 delete [] a; int *a = new int[12];new 和 delete能够动态的创建数组,删除数组。
char *a = new char;
delete a;
char *a = new char[12] //创建一个12个字节的字符数组
delete [] a;
int *a = new int[12]; //创建一个12个字节整形数组
delete [] a;
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int main() { int *a = new int[10]; for (int i = 0; i < 10; i ++) { a[i] = i; } for (int i = 0; i < 10; i ++) { cout << a[i] << endl; } delete [] a; return 0; }
创建二维数组#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int main() { int **a = new int* [10]; //注意前面的指针是比后面高一级的指针 for (int i = 1; i <= 10; i ++) { //二维指针的创建是一维一维进行的。 a[i-1] = new int[i]; } for (int i = 1; i <= 10; i ++) { for (int j = 0; j < i; j ++) { a[i-1][j] = i; } } for (int i = 1; i <= 10; i ++) { for (int j = 0; j < i; j ++) { cout << a[i-1][j]<<" "; } cout << endl; } for (int i = 1; i <= 10; i ++) { //二维指针的删除是先删除一维指针,在删除二维指针。 delete [] a[i-1]; } delete [] a; return 0; }
注意:
在构造函数中使用new来初始化对象的指针,则应在析构函数中使用delete。
new和delete必须相互兼容。new对应delete,new [] 对应 delete []。
如果有多个构造函数,则必须以相同的方式使用new,要么都带中括号,要么都不带。因为只有一个析构函数,因此所有的构造函数都必须与它兼容。不过,可以在一个构造函数中使用new来初始化指针,而在另一个构造函数中将指针初始化为空,这是因为delete可以用于空指针。
-
New 和Delete
2014-09-05 01:45:43GLIBC里面有对 new和delete两类重载函数的声明: namespae std { extern const nothrow_t nothrow; } void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) __attribute__((__externally_...先看一个例子:
执行:/ nothrow example #include <iostream> // std::cout #include <new> // std::nothrow int main () { char* p = new char [0xffffffff]; if (p==0) std::cout << "Failed!\n"; else { std::cout << "Succeeded!\n"; delete[] p; } return 0; }
我们希望 new能够项 malloc那样,如果不成功,返回NULL,而不是把整个程序挂掉.charles@taotao:~/work$ ./testnew terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped)
这种情况下,可以用另外的一种形式的 new:
然后,编译,执行:// nothrow example #include <iostream> // std::cout #include <new> // std::nothrow int main () { char* p = new(std::nothrow) char [0xffffffff]; if (p==0) std::cout << "Failed!\n"; else { std::cout << "Succeeded!\n"; delete[] p; } return 0; }
charles@taotao:~/work$ ./testnew Failed!
只是返回 NULL, 没有导致整个程序终止.GLIBC里面有对 new和delete两类重载函数的声明:
namespae std { extern const nothrow_t nothrow; } void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) __attribute__((__externally_visible__)); void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) __attribute__((__externally_visible__)); void operator delete(void*) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
在 文件/usr/include/c++/4.8/new里可以查到.在 http://www.cplusplus.com/reference/new/nothrow/
有对参数 std::nothrow_t的说明:
This constant value is used as an argument for operator new and operator new[] to indicate that these functions shall not throw an exception on failure, but return a null pointer instead.
By default, when thenew
operator is used to attempt to allocate memory and the handling function is unable to do so, a bad_alloc exception is thrown. But when nothrow is used as argument fornew
, it returns a null pointer instead.
This constant (nothrow) is just a value of type nothrow_t, with the only purpose of triggering an overloaded version of the function operator new (or operator new[]) that takes an argument of this type.我们也可以写自己的 new和delete函数.
void * operator new(std::size_t size) throw(std::bad_alloc) { void *p = malloc(size); printf("my new is called!!\n"); return p; } void * operator new(std::size_t size, const std::nothrow_t & nothrow) { void *p = malloc(size); printf("ny new(nothrow) is called\n"); return p; } void operator delete(void *p) throw() { free(p); printf("my delete is called\n"); } void operator delete(void *p, std::nothrow_t ¬hrow) { free(p); printf("my delete(nothrow) is called\n"); }
然后,测试函数如下:
编译之后,执行:int main () { char* p = new (std::nothrow) char; if (p==0) std::cout << "Failed!\n"; else { std::cout << "Succeeded!\n"; delete p; } return 0; }
charles@taotao:~/work$ ./testnew ny new(nothrow) is called Succeeded! my delete is called
-
New和Delete
2010-11-28 11:18:00比如说new操作符(new operator)和operator new的区别。 当你写这样的代码: string *ps = new string("Memory Management"); 你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义...人们有时似乎喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。
当你写这样的代码:
string *ps = new string("Memory Management");
你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为。
你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。
函数operator new 通常这样声明:
void * operator new(size_t size);
返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。(假如你喜欢,你能写一种operator new函数,在返回一个指针之前能够初始化内存以存储一些数值,但是一般不这么做。)参数size_t确定分配多少内存。你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。(有关operator new更多的信息参见Effective C++ 条款8至条款10。)
你一般不会直接调用operator new,但是一旦这么做,你可以象调用其它函数一样调用它:
void *rawMemory = operator new(sizeof(string));
操作符operator new将返回一个指针,指向一块足够容纳一个string类型对象的内存。
就象malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。operator new所了解的是内存分配。把operator new 返回的未经处理的指针传递给一个对象是new操作符的工作。当你的编译器遇见这样的语句:
string *ps = new string("Memory Management");
它生成的代码或多或少与下面的代码相似(更多的细节见Effective C++条款8和条款10,还有我的文章Counting object里的注释。):
void *memory = // 得到未经处理的内存
operator new(sizeof(string)); // 为String对象
call string::string("Memory Management") //初始化
on *memory; // 内存中
// 的对象
string *ps = // 是ps指针指向
static_cast(memory); // 新的对象
注重第二步包含了构造函数的调用,你做为一个程序员被禁止这样去做。你的编译器则没有这个约束,它可以做它想做的一切。因此假如你想建立一个堆对象就必须用new操作符,不能直接调用构造函数来初始化对象。
Placement new
有时你确实想直接调用构造函数。在一个已存在的对象上调用构造函数是没有意义的,因为构造函数用来初始化对象,而一个对象仅仅能在给它初值时被初始化一次。但是有时你有一些已经被分配但是尚未处理的的(raw)内存,你需要在这些内存中构造一个对象。你可以使用一个非凡的operator new ,它被称为placement new。
下面的例子是placement new如何使用,考虑一下:
class Widget {
public:
Widget(int widgetSize);
...
};
Widget * constrUCtWidgetInBuffer(void *buffer,
int widgetSize)
{
return new (buffer) Widget(widgetSize);
}
这个函数返回一个指针,指向一个Widget对象,对象在转递给函数的buffer里分配。当程序使用共享内存或memory-mapped I/O时这个函数可能有用,因为在这样程序里对象必须被放置在一个确定地址上或一块被例程分配的内存里。(参见条款4,一个如何使用placement new的一个不同例子。)
在constructWidgetInBuffer里面,返回的表达式是:
new (buffer) Widget(widgetSize)
这初看上去有些生疏,但是它是new操作符的一个用法,需要使用一个额外的变量(buffer),当new操作符隐含调用operator new函数时,把这个变量传递给它。被调用的operator new函数除了待有强制的参数size_t外,还必须接受void*指针参数,指向构造对象占用的内存空间。这个operator new就是placement new,它看上去象这样:
void * operator new(size_t, void *location)
{
return location;
}
这可能比你期望的要简单,但是这就是placement new需要做的事情。究竟operator new的目的是为对象分配内存然后返回指向该内存的指针。在使用placement new的情况下,调用者已经获得了指向内存的指针,因为调用者知道对象应该放在哪里。placement new必须做的就是返回转递给它的指针。(没有用的(但是强制的)参数size_t没有名字,以防止编译器发出警告说它没有被使用;见条款6。) placement new是标准C++库的一部分。为了使用placement new,你必须使用语句#include (或者假如你的编译器还不支持这新风格的头文件名)。
让我们从placement new回来片刻,看看new操作符(new operator)与operator new的关系,你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。假如你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。假如你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。假如你想在一块已经获得指针的内存里建立一个对象,应该用placement new。
Deletion and Memory Deallocation
为了避免内存泄漏,每个动态内存分配必须与一个等同相反的deallocation对应。函数operator delete与delete操作符的关系与operator new与new操作符的关系一样。当你看到这些代码:
string *ps;
...
delete ps; // 使用delete 操作符
你的编译器会生成代码来析构对象并释放对象占有的内存。
Operator delete用来释放内存,它被这样声明:
void operator delete(void *memoryToBeDeallocated);
因此, delete ps;
导致编译器生成类似于这样的代码:
ps->~string(); // call the object's dtor
operator delete(ps); // deallocate the memory
// the object occupied
这有一个隐含的意思是假如你只想处理未被初始化的内存,你应该绕过new和delete操作符,而调用operator new 获得内存和operator delete释放内存给系统:
void *buffer = // 分配足够的
operator new(50*sizeof(char)); // 内存以容纳50个char
//没有调用构造函数
...
operator delete(buffer); // 释放内存
// 没有调用析构函数
这与在C中调用malloc和free等同。
假如你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转递给它的指针。谁知道这个指针来自何方?而你应该显式调用对象的析构函数来解除构造函数的影响:
// 在共享内存中分配和释放内存的函数 void * mallocShared(size_t size);
void freeShared(void *memory);
void *sharedMemory = mallocShared(sizeof(Widget));
Widget *pw = // 如上所示,
constructWidgetInBuffer(sharedMemory, 10); // 使用
// placement new
...
delete pw; // 结果不确定! 共享内存来自
// mallocShared, 而不是operator new
pw->~Widget(); // 正确。 析构 pw指向的Widget,
// 但是没有释放
//包含Widget的内存
freeShared(pw); // 正确。 释放pw指向的共享内存
// 但是没有调用析构函数
如上例所示,假如传递给placement new的raw内存是自己动态分配的(通过一些不常用的方法),假如你希望避免内存泄漏,你必须释放它。(参见我的文章Counting objects里面关于placement delete的注释。)
Arrays
到目前为止一切顺利,但是还得接着走。到目前为止我们所测试的都是一次建立一个对象。怎样分配数组?会发生什么?
string *ps = new string[10]; // allocate an array of
// objects
被使用的new仍然是new操作符,但是建立数组时new操作符的行为与单个对象建立有少许不同。第一是内存不再用operator new分配,代替以等同的数组分配函数,叫做operator new[](经常被称为array new)。它与operator new一样能被重载。这就答应你控制数组的内存分配,就象你能控制单个对象内存分配一样(但是有一些限制性说明,参见Effective C++ 条款8)。
(operator new[]对于C++来说是一个比较新的东西,所以你的编译器可能不支持它。假如它不支持,无论在数组中的对象类型是什么,全局operator new将被用来给每个数组分配内存。在这样的编译器下定制数组内存分配是困难的,因为它需要重写全局operator new。这可不是一个能轻易接受的任务。缺省情况下,全局operator new处理程序中所有的动态内存分配,所以它行为的任何改变都将有深入和普遍的影响。而且全局operator new有一个正常的签名(normal signature)(也就单一的参数size_t,参见Effective C++条款9),所以假如你 决定用自己的方法声明它,你马上使你的程序与其它库不兼容基于这些考虑,在缺乏operator new[]支持的编译器里为数组定制内存治理不是一个合理的设计。)
第二个不同是new操作符调用构造函数的数量。对于数组,在数组里的每一个对象的构造函数都必须被调用:
string *ps = // 调用operator new[]为10个
new string[10]; // string对象分配内存,
// 然后对每个数组元素调用
// string对象的缺省构造函数。
同样当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operator delete来释放内存。
就象你能替换或重载operator delete一样,你也替换或重载operator delete[]。在它们重载的方法上有一些限制。请参考优秀的C++教材。
new和delete操作符是内置的,其行为不受你的控制,凡是它们调用的内存分配和释放函数则可以控制。当你想定制new和delete操作符的行为时,请记住你不能真的做到这一点。你只能改变它们为完成它们的功能所采取的方法,而它们所完成的功能则被语言固定下来,不能改变。(You can modify how they do what they do, but what they do is fixed by the language) -
C++ new和delete
2020-05-07 20:23:14在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数。...在cpp中,这两个函数仍然可以使用,但是C++又新增了两个关键字,new 和 delete:new 用来动态分配内存,delete 用来释放内... -
new 和delete
2007-12-08 13:06:00#include #include using namespace std; void main() { int *a = new int[34]; int *b = new int[]; int (*c)[2] = new int[34][2]; int (*d)[2] = new int[][2]; int (*e)[2][3] = new int[34][2][3]; int (*f -
重载new和delete
2017-12-04 14:41:42重载new和delete -
定制new和delete
2016-06-14 10:26:13在看《effective C++》第8章(定制new和delete)时,发现自己对new和delete理解的并不是那么深刻。 为什么要定制new和delete呢,因为在某些环境下(嵌入式),定制的new和delete效率会更高。 我在之前的文章“重载new... -
new和delete用法
2017-03-06 13:53:30在 C++ 中,你也许经常使用 new 和 delete 来动态申请和释放内存,但你可曾想过以下问题呢? new 和 delete 是函数吗?new [] 和 delete [] 又是什么?什么时候用它们?你知道 operator new 和 operator delete ... -
placement new和placement delete(重载new和delete2)
2015-11-21 11:30:20placement new和placement delete参考:《Effective C++》placement new和placement ...2 如何使用placement版本的new和delete 3 从内存泄露出发 a 什么时候new一个对象会发生内存泄露 b 当placement new和placement -
new和delete底层解析
2018-04-05 10:26:441.new/delete 和operator new/operator delete和malloc/free的关系 2.new时底层处理的机制 3.new/delete和malloc/free的区别 1.new/delete 和operator new/...先写个栗子看看new和delete的用法: int main... -
C++ 的 new 和 delete : new operator, operator new, placement new, delete operator, operator delete
2015-05-23 17:15:18C++ 的 new 和 delete :new operator, operator new, placement new, delete operator, operator delete 1. new operator new operator 完成了两件事情:用于申请内存和初始化对象。 例如: string* ps = new ... -
new和delete续
2017-12-17 19:27:57new和delete的重载和示例,多参数的重载及示例,string类当中的应用 -
operator new与operator delete函数以及new和delete的实现原理
2019-09-08 11:13:00new和delete是用户进行动态内存申请和释放的操作符; operator new和operator delete是系统提供的全局函数; new在底层调用operator new全局函数来申请空间; delete在底层通过operator delete全局函数来释放空间; ... -
new和delete详解
2017-08-29 09:21:5016、new和delete详解 a.new和delete运算符是用于动态分配和撤销内存的运算符。 对于计算机程序设计而言,变量和对象在内存中的分配都是编译器在编译程序时安排好的,这带来极大的不便,如数组必须大开小用,指针...