解除分配功能排除使用具有两个参数的分配 [英] Deallocation function precludes use of an allocation with two parameter

查看:295
本文介绍了解除分配功能排除使用具有两个参数的分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是从3.7.4.2 N3797:

Here is from 3.7.4.2 N3797:


全局操作符delete []只有两个参数,第二个
它的类型为std :: size_t,是一个通常的解除分配函数。37

The global operator delete[] with exactly two parameters, the second of which has type std::size_t, is a usual deallocation function.37

37)这个解除分配函数排除了使用分配函数
void operator new std :: size_t,std :: size_t)作为布局分配
函数

37) This deallocation function precludes use of an allocation function void operator new(std::size_t, std::size_t) as a placement allocation function

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

This note is not clear for me. I would like to look at the real example of that preclusion. Compiler will throw a warning or we have a runtime error? I've been trying to write something like the following:

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

这反映了这种排斥。

推荐答案

如果构造函数在新调用期间抛出异常,类似地声明使用相同的参数将被调用。因此,放置new和delete应该始终以匹配对形式声明。

If the constructor throws an exception during a new call, the similarly declared delete with the same parameters will be called. For this reason, placement new and delete should always be declared in matching pairs.

在这种情况下,删除将具有与数组删除相同的签名,编译器将不能在它们之间进行选择。

In this case, the delete will have the same signature as the array delete and the compiler will not be able to choose between them.

编辑以添加示例代码和输出。

Edited to add sample code and output.

实现被禁止的全局数组布局new:

Your code did not implement the global array placement new that is forbidden:

void * operator new( size_t bytes, size_t )

此程序将说明如何调用全局新增和删除。

This program will illustrate how the global new and delete are called.

#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会得到以下结果: / p>

Compiling with clang 3.4.2 for C++11 gives this result:

$ 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字节的分配是例外。

The allocation of 33 bytes is the exception. The exception and the array are both deleted with the same delete function.

使用C ++ 14规则进行编译可得到以下结果:

Compiling with C++14 rules gives this result:

$ 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规则进行编译会产生以下结果:

Disabling the invalid section and compiling with C++14 rules gives this result:

$ 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. =====

请注意,现在使用不同的删除功能删除数组。它在第76行是相同的删除功能,删除了编译为C ++ 11时的数组布局new。

Notice that the array is now deleted with a different delete function. It is the same delete function at line 76 that deleted the array placement new when compiled as C++11.

这篇关于解除分配功能排除使用具有两个参数的分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆