We know from c++ 11(also true in c++98/03 standard) standard(see below), we cannot try to replace the operator new function - placement form in global space as it has already been defined.

18.6.1.3 Placement forms [new.delete.placement]

These functions are reserved, a C++ program may not define functions that displace the versions in the Standard C++ library (17.6.4). The provisions of (3.7.4) do not apply to these reserved placement forms of operator new and operator delete.

This has been proven by point 2> in the snippet below, compile error as expected.

But I can still override the placement new in class level,that works fine, see point (2) in snippet below. Why is that? Shouldn't compile should try to prevent (2) as well according to standard ???

See my snippet below:

class Test
{
public:
    Test(int i):m_i(i) { cout << "Test::Test()" << endl; }
    ~Test() { cout << "Test::~Test()" << endl; }

    //(1)class level override placement new
    void* operator new (std::size_t size) throw (std::bad_alloc) {
        cout << "My class level new" << endl;
        return malloc(size);
    }

    //(2)class level override placement new
    void* operator new (std::size_t size, void* ptr) throw() {
        cout << "My class level non-throwing placement new" << endl;
        return ptr;
    }
private:
    int m_i;

};

//<1>global replacement for operator new - single object form
void* operator new (std::size_t size) throw (std::bad_alloc) {
    cout << "My global new" << endl;
    return malloc(size);
}


//<2>global replacement for operator new - replcement  form
//NB. This is a attempt that definitely fails according to c++ stadnard:
//does get compile error: error: redefinition of 'void* operator new(std::size_t, void*)'
/*
void* operator new (std::size_t size, void* ptr) throw() {
    cout << "My global non-throwing placement new" << endl;
    return ptr;
}
*/

int main() {
    Test* p = new Test(1);
    delete p;

    cout << "" << endl;
    void* mem = operator new(sizeof(Test));
    Test* p2 = new(mem) Test(1);
    p2->~Test();
    operator delete (mem);

    return 0;
}

Below is output as expected:

My class level new
My global new
Test::Test()
Test::~Test()

My global new
My class level non-throwing placement new
Test::Test()
Test::~Test()

================================================================================== Further clarification for my question:

18.6.1.3 Placement forms These functions are reserved, a C++ program may not define functions that displace the versions in the Standard C++ library (17.6.4). The provisions of (3.7.4) do not apply to these reserved placement forms

of operator new and operator delete.

This explains the expected compile error at point <2> in my snippet, so this one is ok.

But why I can displace the placement forms in the class level at point (2) inside the class clarification?

有帮助吗?

解决方案

§18.6.1.3 lists the following forms:

void* operator new(std::size_t size, void* ptr) noexcept;
void* operator new[](std::size_t size, void* ptr) noexcept;
void operator delete(void* ptr, void*) noexcept;
void operator delete[](void* ptr, void*) noexcept;

The rule that "a C++ program may not define functions that displace the versions in the Standard C++ library" applies only to these four function declarations, which are not in any namespace. If you make your own version in a class or a namespace, that's fine.

In fact, sometimes you have to provide your own placement new. If you declare a normal operator new in your class, it will hide the placement new provided by the standard library, and you'll need to add your own placement new in the class if you ever want to use the new (ptr) T(...) syntax.

This simply provides a guarantee that the call ::new (ptr) T(...) is guaranteed to behave like the standard placement new. (Note the :: prefix.)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top