概述
C++是一种面向对象编程语言,它提供了一系列的内存管理工具,其中最重要的就是new操作符。new是用来动态分配内存的,它能够在程序运行时创建一个新的对象,并返回一个指向该对象的指针。
在C++中,使用new操作符可以分配两种类型的内存:堆内存和自由存储区。堆内存是在程序运行时动态分配的内存,通常用于存储较大的数据结构,如数组和对象。自由存储区是程序运行时维护的一段内存区域,可以用来存储较小的数据结构,如指针和变量。
new和operator new
new
为C++中的一个关键字(准确地说是操作符)。operator new
是一个C++库函数
- new操作符执行以下操作
- operator new(unsigned int) ------ 分配内存空间
- Demo::Demo() -------- 调用适当的构造函数在上面申请的空间上构建对象,更改 指针的属性 .new
- operator new执行以下操作
- 分配所需大小的内存空间。
- 返回指向分配内存空间的指针。
总的来说,new 在分配内存后会自动调用对象的构造函数,而 operator new 只是为分配内存提供了一种方法。在大多数情况下,C++程序员通常使用 new 而不是 operator new,因为 new 提供了更方便的语法,并自动处理对象的构造和析构。
new 重载格式
- 以成员函数的形式重载 new 运算符
void * className::operator new( size_t size ){ //TODO: }
- 以全局函数的形式重载 new 运算符
void * operator new( size_t size ){ //TODO: }
void * opertor new (size_t size ,const char * file ,long line) { cout << file << “:” << line << endl; cout << "这是第" <<i++<<"次使用new操作符"<< endl; void *p = malloc(size); return p } void operator delete(void* ptr) { std::cout << "Deallocating memory" << std::endl; std::free(ptr); } void * operator new(size_t i)//new的重载示例 { cout << "使用new操作符" << endl; if (i > sizeof(A))//如果调用此new的是派生类(大于A) { return ::operator new(i);//那么调用全局的正式new } return malloc(i); }
原则:
- 只分配所要求的空间,不调用相关对象的构造函数。当无法满足所要求分配的空间时,则如果有new_handler,则调用new_handler,否则如果没要求不抛出异常(以nothrow参数表达),则执行bad_alloc异常,否则返回回0 .
- 可以被重载
- 重载时,返回类型必须声明为
void*
- 重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t
- 重载时,可以带其它参数
源码
operator new源码
//头文件先忽略 using std::new_handler; using std::bad_alloc;// using 声明 #if _GLIBCXX_HOSTED// 如果 有这个宏使用 std的malloc using std::malloc; #else// 没有则使用c语言的malloc // A freestanding C runtime may not provide "malloc" -- but there is no // other reasonable way to implement "operator new". extern "C" void *malloc (std::size_t); #endif _GLIBCXX_WEAK_DEFINITION void * operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc) { void *p; // new_handler 以后说明,但是可以看出首先我们根据入口参数 sz的大小分配内存, // 如果sz为0 则令其为1 ,然后在while循环中调用malloc申请内存 // 直到 申请成功 或者 抛出异常或者 abort /* malloc (0) is unpredictable; avoid it. */ if (sz == 0) sz = 1; while (__builtin_expect ((p = malloc (sz)) == 0, false)) { new_handler handler = std::get_new_handler (); if (! handler) _GLIBCXX_THROW_OR_ABORT(bad_alloc()); handler (); } return p; }
placement new(特殊的new操作)(不分配内存 + 构造函数的调用)
// Default placement versions of operator new. inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT { return __p; } //可以看到 placement new 什么内存都没有申请 只是直接返回 指针 那么placement new的步骤和new的步骤像只是没有申请任何的内存但是调用了构造函数 //当我们使用 `obj p = new( alreadyExistPoint )obj()` 意味着在已经分配内存的 内容里调用obj的构造函数 那么步骤是这样的 //调用 重载的 operator new 函数 void * tmp_point = ::operator new( sizeof( obj ) ,alreadyExistPoint) ; // 更改 指针的属性 obj * point = static_cast
array new源码
_GLIBCXX_WEAK_DEFINITION void* operator new[] (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc) { return ::operator new(sz); }
new和malloc的区别
- 语法:new 是 C++ 的运算符,而 malloc 是 C 标准库函数。因此,new 可以调用类的构造函数,而 malloc 不行。
- 返回类型:new 返回指向已分配的内存空间的指针,并且可以自动确定所需内存的大小,而 malloc 返回
void*
,需要手动指定分配内存的大小。- 异常处理:如果 new 无法分配所需的内存空间,它将抛出 std::bad_alloc 异常,而 malloc 只会返回一个空指针。
- 用法:new 可以使用在任何需要分配对象内存的情况下,malloc 则更适用于动态数组的分配。
- 内存对齐:new 会自动保证返回的指针所指向的内存是按照所需类型的对齐方式对齐的,而 malloc 则需要手动调用一些特定的函数才能确保对齐。
在使用时,通常在 C++ 中使用 new,在 C 中使用 malloc。
operator new和malloc的区别
operator new 和 malloc 都是用于动态分配内存的函数。它们之间的主要区别如下:
- operator new 是 C++ 中的操作符函数,而 malloc 是 C 标准库中的函数。
- operator new 用于在堆上分配特定类型的内存,而 malloc 分配的是一段无类型的内存空间。
- operator new 会自动调用构造函数初始化对象,而 malloc 不会。
- operator new 可以被用户自定义,从而实现定制的内存分配行为,而 malloc 不支持这样的定制。
- operator new 还支持重载,可以根据需要重载不同版本的 operator new 来实现不同的内存分配策略,而 malloc 不支持重载。
- operator new 和 malloc 返回的指针类型不同,operator new 返回的指针类型是所请求类型的指针,而 malloc 返回的是
void*
类型的指针,需要手动转换为所需的类型。在 C++ 中,通常使用 operator new 来分配内存,特别是在需要为对象类型分配内存时,而在 C 中,则通常使用 malloc。