3

我们从 c++ 11(在 c++98/03 标准中也是如此)标准中知道(见下文),我们不能尝试替换 operator new 函数 - 全局空间中的放置形式,因为它已经定义。

18.6.1.3 安置表格 [new.delete.placement]

这些函数是保留的,C++ 程序可能不会定义取代标准 C++ 库 (17.6.4) 中的版本的函数。(3.7.4) 的规定不适用于 operator new 和 operator delete 的这些保留放置形式。

下面的代码片段中的第 2 点已经证明了这一点,按预期编译错误。

但是我仍然可以覆盖类级别中的新位置,效果很好,请参见下面片段中的第 (2) 点。这是为什么?不应该编译应该尽量防止(2)以及根据标准???

请参阅下面的我的片段:

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;
}

以下是预期的输出:

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()

==================================================== ================================= 进一步澄清我的问题:

18.6.1.3 放置形式这些函数是保留的,C++ 程序不能定义替换 标准C++ 库 (17.6.4) 中的版本的函数。(3.7.4) 的规定不适用于这些保留的安置表格

运算符 new 和运算符 delete。

这解释了我的代码片段中 <2> 点处的预期编译错误,所以这个没问题。

但是为什么我可以在班级说明中的第(2)点取代班级级别的安置表格?

4

1 回答 1

2

§18.6.1.3 列出了以下形式:

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;

“C++ 程序不得定义取代标准 C++ 库中版本的函数”的规则仅适用于这四个函数声明,它们不在任何命名空间中。如果您在类或命名空间中制作自己的版本,那很好。

事实上,有时您必须提供自己的新展示位置。如果你operator new在你的类中声明一个 normal ,它将隐藏标准库提供的放置 new ,如果你想使用new (ptr) T(...)语法,你需要在类中添加你自己的放置 new 。

这只是提供了保证调用::new (ptr) T(...)的行为与标准放置 new 一样的保证。(注意::前缀。)

于 2012-10-17T15:06:59.993 回答