我想在C ++中实现我自己的new
版本,它带有一个分配器。我可以这样做:
template <class T>
void *operator new(std::size_t size, project::specialized_allocator<T> &a) {
return a.allocate(size);
}
然后我可以将此分配器用于:
project::specialized_allocator<int> A;
int *i = new (A) int;
但是,我也可以打电话:
int *i = new (nullptr) int;
并且Clang并没有抱怨,而是编译代码。我不确定这应该做什么&amp;为什么它没有使用类型错误进行编译失败。 nullptr
不是project::specialized_allocator<T> &
。
我得到了类似的怪异:
int *i = new (i) int;
这应该如何运作?为什么这些例子没有输入检查?
答案 0 :(得分:7)
现有的placement new
运算符会将void*
或std:nothrow_t
作为其第二个参数。
第一个用于在现有存储器地址处分配对象。这就是new (nullptr)
和new (i)
编译的原因,因为它们都可以转换为void*
。
第二个用于告诉标准分配返回NULL指针,而不是在分配失败时抛出std::bad_alloc
异常。
您可以定义其他参数,但必须确保您传递的任何参数都可以转换为参数类型,而不是void*
或std::nothrow_t
,否则将调用标准运算符您的自定义运算符。
答案 1 :(得分:2)
您正在使用的语法称为placement new,而new
的参数应该是指针。 Placement new实际上并没有分配任何东西;它只是在你指定的位置构造一个对象。
当您编写new (nullptr)
时,您告诉它在地址0处构造一个对象,而new (i)
正在从未初始化指针获取的地址处构造它。这两个都会在运行时导致未定义的行为,因为它们涉及取消引用null和未初始化的指针。