:: (可选) new ( 类型 ) 初始化器(可选) | (1) | ||||||||
:: (可选) new new类型 初始化器(可选) | (2) | ||||||||
:: (可选) new ( 布置参数) ( 类型 ) 初始化器(可选) | (3) | ||||||||
:: (可选) new ( 布置参数) new类型 初始化器(可选) | (4) | ||||||||
1.
auto p = new(int)(6);
使用值初始化
2.
auto p = new int(6);
一样值初始化
1和2都是动态申请内存的,并没有多大区别
布置new
如果提供了 布置参数,那么它们会作为额外实参传递给分配函数。这些分配函数被称作“布置 new”,这来源于标准分配函数 void* operator new(std::size_t, void*),它直接返回未更改的第二实参。它被用于在已分配的存储中构造对象
3.
struct X { X() { puts(__func__); } }; void* operator new(size_t n) { std::cout << __func__ << '\n'; return malloc(n); } int main() { char c = 0; auto c2 = ::new(reinterpret_cast<void*>(c))X; }未使用初始化器
4.
struct X { X() { puts(__func__); } }; void* operator new(size_t n) { std::cout << __func__ << '\n'; return malloc(n); } int main() { char c = 0; auto c2 = ::new(reinterpret_cast<void*>(c))(X); }第三和第三种其实也没什么区别,类型加了个括号
我们一般提起new一般默认是想说申请动态内存的,那么new做了什么事情?
new关键字只做了两件事,调用operator new 调用对象构造函数,我们可以直接重载new,即operator new
- void* operator new(size_t n) {
- std::cout << __func__ << '\n';
- return malloc(n);
- }
operator new[]是同理,不再强调。
我们也可以直接调用标准库提供的operator new,它就没有构造对象,只是申请了内存,返回了一个void*的指针
auto p = operator new(10);
申请了10个字节的内存,返回了一个void*的指针,p的类型就是void*