Search code examples
c++operator-overloadinglanguage-lawyernew-operator

Why does overloading operator new change the behavior of new[]?


Below is a code snippet run under 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;
}  

Questions:

  1. As we know, if we want to change the behavior of new[] we just need to define and replace the default operator new[]. However, why does overloading operator new also change its behavior? Is such behavior implementation defined or required by the standard? Is there any way to stop that because I just want the default behavior for new[]?

  2. Based on question 1, if overloading operator new changes new[]'s behavior, why isn't func1, but func2 called in new A[2] statement?


supplement:

From another code snippet, cppref comments int* p2 = new int[10]; // guaranteed to call the replacement in C++11. It seems like such behavior is guaranteed in the C++11 standard for the first time.


Solution

  • Is such behavior implementation defined or required by the standard?

    According to [new.delete.array]/4:

    void* operator new[](std::size_t size);
    

    Default behavior: Returns operator new(size).

    By replacing ::new(std::size_t), you make ::new[](std::size_t) call your custom allocation function. This explains the observed behaviour.


    Why isn't func1,but func2 called in new A[2] statement?

    It seems new A[x] default behaviour is to call ::operator new[], but I cannot tell why. (This is wrong, see StoryTeller answer).