为什么重载operator new会改变new []的行为?

big*_*iao 2 c++ operator-overloading new-operator language-lawyer

以下是在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;
}  
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 众所周知,如果我们想改变行为,new[]我们只需要定义和替换默认值operator new[].但是,为什么重载operator new也会改变它的行为呢?标准是否定义或要求此类行为实施?有没有办法阻止它,因为我只想要默认行为new[]

  2. 根据问题1,如果重载operator new更改new[]的行为,为什么不是func1,但func2new A[2]声明中调用?


补充:

另一个代码片段,cppref注释int* p2 = new int[10]; // guaranteed to call the replacement in C++11.看起来第一次在C++ 11标准中保证了这种行为.

Sto*_*ica 5

我想补充@ YSC的答案,并解决

为什么不func1,但func2new A[2]声明中呼吁?

这一段都在这里:

[expr.new]/9

如果new-expression以一元运算?::符开头,则在全局范围中查找分配函数的名称.否则,如果分配的类型是类类型T或其数组,则在范围内查找分配函数的名称T.如果此查找未能找到名称,或者分配的类型不是类类型,则在全局范围中查找分配函数的名称.

因此,new A[2]首先要在范围内寻找合适的分配函数A.该功能需要命名operator new[].没有A::operator new[]成员,因此查找失败.然后在全局范围中查找该函数.这意味着::operator new[]找到了.它是分配整数数组的相同分配函数.就像YSC的详细信息一样,它::operator new会让你感动,这就是你观察func2被召唤的原因.