当前位置: 首页 > 知识库问答 >
问题:

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

骆利
2023-03-14

这是来自3.7.4.2的N3797:

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

37)此解除分配函数排除使用分配函数空运算符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(){ }

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

共有1个答案

施阳曜
2023-03-14

如果构造函数在新调用期间抛出异常,则将调用具有相同参数的类似声明的delete。因此,placement 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字节的分配是例外。使用相同的删除函数删除异常和数组。

使用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. =====

请注意,现在使用不同的删除函数删除数组。当编译为C 11时,删除数组放置新的与第76行的删除函数相同。

 类似资料:
  • 我正在使用Varnish cache 6.0。6.有时我需要基于URL忽略GET参数和任何标题使缓存无效。我为此使用命令。 获取用于检索内容的命令。他们得到的结果是不同的。 BAN命令禁止两个缓存。 清漆配置 但是,ban命令仅对第一个请求使缓存无效。第二个请求保持缓存状态。如何使以

  • 本文向大家介绍php定义一个参数带有默认值的函数实例分析,包括了php定义一个参数带有默认值的函数实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例分析了php定义一个参数带有默认值的函数用法。分享给大家供大家参考。具体分析如下: php的函数参数可以指定默认值,指定默认值后,调用时如果不给该参数赋值,则该参数就使用默认值 希望本文所述对大家的php程序设计有所帮助。

  • 使用XPath,我想“匹配整个单词”(用户选项,就像VS搜索一样)。 似乎函数

  • 问题内容: 我想将Python函数的某些参数提前“传递”给另一个函数。 这是我正在做的简化: 我不想使用某种形式的传递,以后再进行分解,因为传递给我的函数不知道传递给它。 对于小组项目来说,这有点太聪明了……是否有更直接或更Python的方法来执行此操作? 谢谢! 问题答案: 这称为currying或部分应用程序。您可以使用内置的functools.partial()。像下面这样的东西会做你想要的

  • 我有一个问题,归结为试图将具有特定参数类型的函数分配给期望具有泛型类型的函数的变量: 游乐场版。 TypeScript给出以下错误: 类型“(v:string[]))= 这个错误对我来说没有多大意义,因为对于泛型,似乎是一个非常合理的类型。 有一个相关的问题具有相同的基本问题,但是答案是特定于该问题的情况的:为什么实现接口的TypeScript类不能分配给扩展接口的通用约束?