1

该标准说,在5.3.4[expr.new]/7

当 direct-new-declarator 中的表达式的值为零时,调用分配函数来分配一个没有元素的数组。

并且在3.7.3.1[basic.stc.dynamic.allocation]/2

取消引用作为零大小请求返回的指针的效果是未定义的。

但是如果分配函数是用户定义的并且它知道它返回了一个有效的指针,那么取消引用它仍然是未定义的行为吗?标准可以强制用户代码的未定义行为吗?

我问的原因是另一个毫无意义的尝试初始化非默认构造类型的对象的动态数组。delete[]除了明显没有并且只能用 调用之外,它还有什么问题[0]?我什至aligned_storage正确使用了吗?

#include <type_traits>
#include <stdexcept>
#include <memory>
#include <iostream>

struct T {
   int val;
   T() = delete;
   T(int i) : val(i) {}
   void* operator new[](std::size_t, std::size_t cnt, const T& t)
   {
       typedef std::aligned_storage<sizeof(t),
                    std::alignment_of<T>::value>::type buf;
       T* ptr = reinterpret_cast<T*>(new buf[cnt]);
       std::uninitialized_fill_n(ptr, cnt, t);
       return ptr;
    }
};

int main()
{
    T* a = new(100, T(7)) T[0]; // using zero is legal per 5.3.4/7

    std::cout << "a[0] = " << a[0].val << '\n' // but is this legal?
              << "a[1] = " << a[1].val << '\n'
              << "a[98] = " << a[98].val << '\n'
              << "a[99] = " << a[99].val << '\n';
    delete[] a; // free the 100 aligned_storages
}

试运行:http: //ideone.com/iBW0z

还可以使用 MSVC++ 2010 EE 按预期编译和运行

4

2 回答 2

3

您的代码中有一个烦人的逻辑问题:

新的表达方式:

T* a = new(100, T(7)) T[0];

调用 T 的已删除默认构造函数 [expr.new]/17。;-(

std::vector<T>现在肯定看起来不错... :-)

于 2011-04-05T23:47:03.490 回答
1

使用 a 结果的唯一未定义行为reinterpret_cast是当强制转换返回其原始类型时,因此即使其他一切正常,您也已经拥有 UB。

如果你真的需要这个,为什么不创建一个函数来分配足够大的连续内存块,然后将newsa 堆放T入该内存中呢?

于 2011-04-05T23:25:59.620 回答