我正在使用g ++ 4.9.0和N3797工作草案。我写了以下简单的例子:
#include <iostream>
#include <cstdlib>
using namespace std;
struct A
{
void* operator new[](size_t t, size_t)
{
cout << "allocation" << endl;
return ::operator new[](t);
}
void operator delete[](void *p, size_t t)
{
cout << "deallocation" << endl;
:: operator delete[](p);
}
};
int main()
{
A *a = new (90) A[5];
delete [] a;
}
该示例必须反映3.7.4.2/2节中的以下脚注规则:
全局运算符delete []只有两个参数,第二个 其中的类型为std :: size_t,是一种常见的释放函数.37
37)该解除分配功能排除了使用分配功能 void operator new(std :: size_t,std :: size_t)作为放置分配 功能
但它没有。这是一个bug或脚注只是对实现者的推荐?
答案 0 :(得分:4)
这是非法的,编译器应该发出诊断信息。从§5.3.4[expr.new] / p22开始,强调增加了:
展示位置释放函数的声明与 如果具有相同的位置分配功能的声明 参数数量,参数变换后(8.3.5)全部 参数类型除了第一个是相同的。如果查找找到了 单匹配解除分配函数,该函数将被调用; 否则,不会调用解除分配函数。 如果查找 找到通常的释放函数的双参数形式 (3.7.4.2)和该函数,被视为放置释放 功能,将被选为匹配的分配 功能,程序格式不正确。对于非展示位置分配 函数,正常的释放函数查找用于查找 匹配释放函数(5.3.5)[示例:
struct S { // Placement allocation function: static void* operator new(std::size_t, std::size_t); // Usual (non-placement) deallocation function: static void operator delete(void*, std::size_t); }; S* p = new (0) S; // ill-formed: non-placement deallocation function matches // placement allocation function
- 结束示例]
对您的代码判断generates错误。
但请注意,与全局operator delete
和operator delete[]
不同,作为类成员的双参数operator delete
和operator delete[]
不一定是通常的释放函数(§3.7。 4.2 [basic.stc.dynamic.deallocation] / p2):
如果类
T
具有名为operator delete
的成员释放函数 只有一个参数,那么该函数是通常的 释放功能。如果班级T
未声明此类operator delete
但确实声明了一个名为operator delete
的成员释放函数 正好有两个参数,第二个参数有类型std::size_t
,那么这个函数是一个通常的释放函数。 同样,如果类T
具有名为的成员释放函数operator delete[]
只有一个参数,那么该函数是 通常的(非放置)释放功能。如果T级没有 声明这样的operator delete[]
但确实声明了一个成员 名为operator delete[]
的释放函数恰好有两个 参数,其中第二个类型为std::size_t
,然后是这个 函数是一种常见的释放函数。
因此,与全局释放函数不同,如果声明成员operator delete[] (void *)
,则operator delete[] (void *, std::size_t)
不再是通常的释放函数,而是放置释放函数:
struct A
{
void* operator new[](size_t t, size_t)
{
cout << "allocation" << endl;
return ::operator new[](t);
}
void operator delete[](void *p)
{
cout << "deallocation - usual" << endl;
:: operator delete[](p);
}
void operator delete[](void *p, size_t t)
{
cout << "deallocation - placement" << endl;
:: operator delete[](p);
}
};
clang no longer报告此代码出错。
答案 1 :(得分:0)
我相信你会得到未定义的行为。我认为如果构造函数失败并且数组必须被释放,则无法区分正确的放置删除函数和大小的删除函数。