以下是在vs2015下运行的代码段:
#include<iostream>
using namespace std;
class A {
public:
A(int _a,int _b){}
//func1
void* operator new(size_t sz) {
cout << "func1"<<endl;
return malloc(sz);
}
};
//func2
void* operator new(size_t sz) {
cout << "func2" << endl;
return malloc(sz);
}
int main() {
int* i = new int;//OK,it calls the func2
int* i1 = new int[6];//why does it call the func2,not the implicit default `operator new[]`?
A *a = new A(1, 2);//OK,it calls the func1
A* a1 = new A[2]{ {1,2},{3,4} };//why does it call the func2 instead of func1?
return 0;
}
众所周知,如果我们想要更改new[]
的行为,我们只需要定义并替换默认的operator new[]
。但是,为什么重载operator new
也会改变它的行为? 标准是否定义或要求此类行为实现?有没有办法阻止它,因为我只想要new[]
的默认行为?
根据问题1,如果超载operator new
改变了new[]
的行为,为什么不是func1
,而是{{1在func2
声明中调用?
来自another code snippet,cppref评论new A[2]
这种行为似乎首次在C ++ 11标准中得到保证。
答案 0 :(得分:5)
我想补充@YSC's answer和地址
为什么不是
func1
,而func2
在new A[2]
声明中被调用?
这一段都在那里:
如果 new-expression 以一元
::
运算符开头,那么 在全局范围内查找分配函数的名称。 否则,如果分配的类型是类类型T
或其数组, 在T
的范围内查找分配函数的名称。如果这 查找无法找到名称,或者分配的类型不是类 在类型中,分配函数的名称在全局范围内查找。
所以new A[2]
将首先在A
的范围内寻找合适的分配函数。该函数需要命名为operator new[]
。没有A::operator new[]
成员,因此查找失败。然后在全局范围中查找该函数。这意味着找到了::operator new[]
。它是分配整数数组的相同分配函数。和YSC的详细信息一样,它会调用你移位的::operator new
。这就是你观察func2
被召唤的原因。
答案 1 :(得分:2)
标准是否定义或要求此类行为实施?
void* operator new[](std::size_t size);
默认行为:返回
operator new(size)
。
通过替换::new(std::size_t)
,您可以::new[](std::size_t)
拨打custom allocation function。这解释了观察到的行为。
为什么不是
func1
,而是在func2
声明中调用new A[2]
?
似乎(这是错误的,请参阅StoryTeller的答案)。new A[x]
默认行为是调用::operator new[]
,但我不知道为什么。
答案 2 :(得分:-1)
&#39; operator new&#39;处理其操作数的大小-not type-。数组表单的默认impl将所需大小转发给全局&#39; operator new&#39;。 &#39; operator new&#39;只是一个功能,而不是模板或任何东西。所有神奇的大小计算都是在调用&#39;运算符new&#39;之前进行的。为了使数组删除成为可能,在数组表单返回后添加一些次要的spice。如果在引入C ++的新/删除时模板已存在,语义将更加清晰。