【发布时间】:2026-02-01 08:25:01
【问题描述】:
标准说,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
}
使用 MSVC++ 2010 EE 也可以按预期编译和运行
【问题讨论】:
-
"我问的原因是又一次毫无意义的尝试初始化非默认构造类型的对象的动态数组。" 为什么
std::vector不够?它完全允许这样做。 -
@ildjarn:对于这个目的来说已经绰绰有余了,是的。我只是在探索语言的边界。
-
我也不确定
new运算符返回的偏移量。我认为,对于new所知道的一切,它可以使用等于100 * sizeof(T)的未命名size_t参数调用您的operator new,并将生成的缓冲区偏移100 * sizeof(T)。或者更现实地,用sizeof(size_t)调用它并偏移sizeof(size_t)来存储数组元素的计数(需要知道以后调用多少个dtor),而不是用0的大小调用它。跨度>
标签: c++ c++11 standards-compliance array-initialization