当前位置: 华文星空 > 知识

C++中什么情况下需要重载new运算符?

2021-07-07知识

那是你见识太少了。问你两个问题,不求你能回答,但至少求你能看的懂问题。

1. SIMD 中不少指令是要求数据对齐的,请问要是对齐要求超过了 malloc/new 默认的对齐了,你打算怎么办?

对齐版本的 operator new 重载了解一下?

void * operator new ( std :: size_t count , std :: align_val_t al );

2. new 申请不到内存时,在默认情况下,是会一个循环,不断调用 std::get_new_handler 返回的函数指针,直到分配成功为止的。我觉得这也太坑了,顶多试三次就行了,你打算怎么办?

把你代码里出现 new 的地方全一个一个替换掉么?累死你。

你说用不到这个功能,那是因为都给你封装在底层了,不需要来让你操心了。

我跟你说,要是没重载 new 这个功能,你连最基础的 vector 都实现不了。

vector 最核心的需求是什么?是要求内存分配和对象的构造之间能解耦、解分配和对象的析构之间能解耦。说人话,就是需要先用 allocator.allocate() 方法从分配器中提前分配出内存块, 等推迟到合适的时候,才在这个内存块上构造出对象

那些叫嚣 100 行写出的 vector,其实现都是根本不能用的,里面全是用的 new T[]。

正规的写法必须要用到 placement new —— 这是重载 new 的最机智的利用。

vector 的基本原理如下:

#include <new> #include <iostream> struct Foo { int i ; Foo ( int i ) : i ( i ) { std :: cout << "构造 " << i << std :: endl ; } ~ Foo () { std :: cout << "析构 " << i << std :: endl ; } }; int main () { std :: allocator < Foo > alloc ; Foo * p = alloc . allocate ( 3 ); std :: cout << "分配好缓冲区了" << std :: endl ; for ( int i = 0 ; i < 3 ; ++ i ) { std :: cout << "push_back 第 " << i << " 个元素" << std :: endl ; new ( p + i ) Foo ( i ); } for ( int i = 0 ; i < 3 ; ++ i ) { std :: cout << "pop_back 第 " << i << " 个元素" << std :: endl ; ( p + 2 - i ) ->~ Foo (); } alloc . deallocate ( p , 3 ); std :: cout << "释放完缓冲区了" << std :: endl ; }

输出:

分配好缓冲区了 push_back 第 0 个元素 构造 0 push_back 第 1 个元素 构造 1 push_back 第 2 个元素 构造 2 pop_back 第 0 个元素 析构 2 pop_back 第 1 个元素 析构 1 pop_back 第 2 个元素 析构 0 释放完缓冲区了

你以为 placement new 是 C++ 为其特殊设计的语法?

不是的,placement new 只是一个函数调用而已。它只不过是:

void * operator new ( std :: size_t , void * p ) { return p ; }