Deallocation函数禁止使用带有两个参数的分配



下面是来自3.7.4.2 N3797:

全局操作符delete[]有两个参数,第二个它的类型为std::size_t,是一个常用的释放函数。37

37)这个释放函数排除了分配函数的使用Void操作符new(std::size_t, std::size_t)作为位置分配函数

这张便条我看不清楚。我想看看这个排除的真实例子。编译器会抛出一个警告或者我们有一个运行时错误?我一直在尝试写如下内容:

using std::cout;
struct A
{
    int a;
    A(){ a = 5; }
    void * operator new(std::size_t t, std::size_t)
    {
        void *p = ::operator new(t);
        return p;
    }
};
int main(){ }

我不知道有什么例子能反映这种排除。你能帮我提供一个吗?

如果构造函数在新调用期间抛出异常,则将调用具有相同形参的类似声明的delete。因此,位置new和delete应该总是成对地声明。

在这种情况下,delete将具有与数组delete相同的签名,并且编译器将无法在它们之间进行选择。

编辑添加样例代码和输出。

您的代码没有实现禁止的全局数组位置new:

void * operator new( size_t bytes, size_t )

这个程序将演示如何调用全局new和delete。

#include <stdint.h>
#include <malloc.h>
#include <iostream>
#include <stdexcept>
using namespace std;
struct A
{
    int a;
    A( void )
        : a( 1 )
    {
        cout << __LINE__ << " : A::A()" << endl;
        throw logic_error( "That is .. illogical" );
    }
};
// Placement new with size_t parameter
void * operator new( size_t bytes, size_t )
{
    cout << __LINE__ << " : void * A::operator new( size_t bytes = " << bytes << ", size_t )";
    void *p = malloc( bytes );
    cout << " -> " << p << endl;
    return p;
}
// C++11 : Array placement delete with size_t parameter
// C++14 : Array delete
void operator delete( void *p, std::size_t n ) 
{
    cout << __LINE__ << " : void A::operator delete( void *p = " << p << ", size_t n = " << n << " )" << endl;
    if (p)
        free( p );
}
// Non-array new
void * operator new( size_t bytes )
{
    cout << __LINE__ << " : void * A::operator new( size_t bytes = " << bytes << " )";
    void *p = malloc( bytes );
    cout << " -> " << p << endl;
    return p;
}
// Non-array delete
void operator delete( void *p ) noexcept
{
    cout << __LINE__ << " : void A::operator delete( void *p = " << p << " )" << endl;
    if (p)
        free( p );
}
// Array new
void * operator new[]( size_t bytes )
{
    cout << __LINE__ << " : void * A::operator new[]( size_t bytes = " << bytes << " )";
    void *p = malloc( bytes );
    cout << " -> " << p << endl;
    return p;
}
// Array placement new with size_t parameter
void * operator new[]( size_t bytes, size_t n )
{
    cout << __LINE__ << " : void * A::operator new[]( size_t bytes = " << bytes << ", size_t n = " << n << " )";
    void *p = malloc( bytes );
    cout << " -> " << p << endl;
    return p;
}
// C++11 : Array placement delete with size_t parameter
// C++14 : Array delete
void operator delete[]( void *p, std::size_t n ) 
{
    cout << __LINE__ << " : void A::operator delete[]( void *p = " << p << ", size_t n = " << n << " )" << endl;
    if (p)
        free( p );
}
int main( int, char ** )
{
    A *p = nullptr;
#if 1
    try
    {
        cout << __LINE__ << " : ===== Array placement new allocate with size_t parameter. =====" << endl;
        p = new( (size_t)4 ) A[ 3 ];
        cout << __LINE__ << " : ===== Array placement new succeeded. =====" << endl;
    }
    catch (...)
    {
    }
    cout << __LINE__ << " : ===== Array placement delete. =====" << endl;
    delete[] p;
    p = nullptr;
#endif
    try
    {
        cout << __LINE__ << " : ===== Array new. =====" << endl;
        p = new A[ 3 ];
        cout << __LINE__ << " : ===== Array new succeeded. =====" << endl;
    }
    catch (...)
    {
    }
    cout << __LINE__ << " : ===== Array delete. =====" << endl;
    delete[] p;
    p = nullptr;
    cout << __LINE__ << " : ===== Complete. =====" << endl;
    return 0;
}

使用clang 3.4.2编译c++ 11得到如下结果:

$ clang++ --std=c++11 -o replace_new main.cpp && ./replace_new
88 : ===== Array placement new allocate with size_t parameter. =====
66 : void * A::operator new[]( size_t bytes = 12, size_t n = 4 ) -> 0x80048358
14 : A::A()
40 : void * A::operator new( size_t bytes = 33 ) -> 0x800483d8
76 : void A::operator delete[]( void *p = 0x80048358, size_t n = 4 )
49 : void A::operator delete( void *p = 0x800483d8 )
97 : ===== Array placement delete. =====
105 : ===== Array new. =====
57 : void * A::operator new[]( size_t bytes = 12 ) -> 0x80048358
14 : A::A()
40 : void * A::operator new( size_t bytes = 33 ) -> 0x800483d8
49 : void A::operator delete( void *p = 0x80048358 )
49 : void A::operator delete( void *p = 0x800483d8 )
114 : ===== Array delete. =====
118 : ===== Complete. =====

33字节的分配是例外。使用相同的delete函数删除异常和数组。

使用c++ 14规则编译得到如下结果:

$ clang++ --std=c++1y -o replace_new main.cpp && ./replace_new
main.cpp:89:17: error: 'new' expression with placement arguments refers to non-placement 'operator delete'
            p = new( (size_t)4 ) A[ 3 ];
                ^    ~~~~~~~~~
main.cpp:74:10: note: 'operator delete[]' declared here
    void operator delete[]( void *p, std::size_t n )
         ^
1 error generated.

禁用无效部分并使用c++ 14规则编译会得到以下结果:

$ clang++ --std=c++1y -o replace_new main.cpp && ./replace_new
105 : ===== Array new. =====
57 : void * A::operator new[]( size_t bytes = 12 ) -> 0x80048358
14 : A::A()
40 : void * A::operator new( size_t bytes = 33 ) -> 0x800483d8
76 : void A::operator delete[]( void *p = 0x80048358, size_t n = 12 )
49 : void A::operator delete( void *p = 0x800483d8 )
114 : ===== Array delete. =====
118 : ===== Complete. =====

注意,现在用不同的delete函数删除了数组。在编译为c++ 11时,与第76行删除数组位置new的delete函数相同。

最新更新