new 的基本职能
创建一个存在时间不被作用域所影响的 object。
步骤:
- 分配空间
- 初始化对象
- 返回空间
使用 new 的四种语法
- new (type ) new-initializer (optional)
- new type new-initializer (optional)
- new (placement-args ) (type ) new-initializer (optional)
- new (placement-args ) type new-initializer (optional)
组成介绍:
- type 比如 int, double
- new-initializer 大括号内的表达式, 用于指定初值, 如 new double[]{1, 2, 3};
- placement-args 额外的参数,在 type 之前, 如 new(2,f) T;
另一个 placement-args 的例子
重载 void* operator new(std::size_t size)
这个函数要负责空间的分配。
注意不需要负责初始化对象的工作。
例子:
#include <iostream>
class Foo {
public:
void* operator new(std::size_t size)
{
std::cout << "operator new" << std::endl;
return std::malloc(size);
}
};
int main()
{
Foo* m = new Foo;
std::cout << sizeof(m) << std::endl;
delete m;
return 0;
}
重载 void* operator new(std::size_t size, T otherarg)
是 new 重载的另一种形式, 这个函数不负责分配新的空间。
这种重载函数对应了 placement new。
它让我们可以在 new 时传入额外参数, 并进行一些操作。
#include <iostream>
class Foo {
public:
void* operator new(std::size_t size, int num)
{
std::cout << "operator new" << std::endl;
std::cout << "num is " << num << std::endl;
return std::malloc(size);
}
};
int main()
{
Foo* m = new(100) Foo;
std::cout << sizeof(m) << std::endl;
delete m;
return 0;
}
开源项目中的例子
llvm 的 User.cpp 中重载了 new, 部分代码如下:
void *User::operator new(size_t Size, unsigned Us) {
return allocateFixedOperandUser(Size, Us, 0);
}
void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) {
return allocateFixedOperandUser(Size, Us, DescBytes);
}
void *User::operator new(size_t Size) {
// Allocate space for a single Use*
void *Storage = ::operator new(Size + sizeof(Use *));
Use **HungOffOperandList = static_cast<Use **>(Storage);
User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1);
Obj->NumUserOperands = 0;
Obj->HasHungOffUses = true;
Obj->HasDescriptor = false;
*HungOffOperandList = nullptr;
return Obj;
}
参考
operator new, operator new[] - cppreference.com