专业新

时间:2014-05-22 22:22:49

标签: c++ clang

我想在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;

这应该如何运作?为什么这些例子没有输入检查?

2 个答案:

答案 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和未初始化的指针。