操作员删除签名意外行为 [英] Operator delete signature unexpected behavior

查看:117
本文介绍了操作员删除签名意外行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在他的书C ++编程语言(第4版)中,stroustroup提到全局运算符new& delete可以通过编写具有以下签名的全局函数来重载:

In his book C++ Programming Language(4th ed), stroustroup has mentioned that the global operator new & delete can be overloaded by writing global functions with the following signatures:

void* operator new(size_t);               // use for individual object
void* operator new[](size_t);             // use for array
void operator delete(void*, size_t);      // use for individual object
void operator delete[](void*, size_t);    // use for array

注意:传递size_t参数删除以确定正确的对象大小,具体来说,当删除基指针指向的派生对象时(基本需要虚拟dtor,以便传递正确的大小)。

NOTE: The size_t parameter is passed for the delete to determine the correct object size specifically when deleting a derived object pointed by a base pointer(base needs virtual dtor so that correct size is passed).

重载单个对象的全局版本。操作员新工作正常。操作符删除与上面的签名工作正常,但删除不会被调用。如果我更改删除签名,以便它只是一个void *,它会得到调用。可能的问题:

I was trying to overload the global versions for the individual object. The operator new works fine. The operator delete with the above signature works fine, but delete doesn't get called. If I change the delete signature so that it just takes a void *, it does get called. What could be the problem:

这里是代码:

void * operator new (size_t size)
{
    cout << "My operator new called\n";
    auto p = malloc(size);
    return p;
}

void operator delete (void * ptr, size_t size) // Removing size_t parameter makes it work
{
    cout << "My operator delete called\n";
    free(ptr);
}

奇怪的是,如果我让操作员删除类,所以它的重载只是为那个类,删除签名(与size_t和没有size_t)似乎工作!

Strange is also the fact that if I make the operator delete a member of a class so that its overloaded just for that class, both delete signatures(with size_t and without size_t) seem to work!

在delete中传递size_t参数看起来合乎逻辑,我提到的注。但是,这种行为的原因是什么?我使用VS2013测试示例。

Passing size_t parameter in delete does seem logical as explained in the NOTE I had mentioned. But what could be the reason for this behavior? I am using VS2013 for testing out the examples.

推荐答案

从C ++ 1y草稿:

From the C++1y draft:


5.3.5删除 [expr.delete]



[...]

11当执行delete-expression时,将使用要回收的存储块的地址作为其第一个参数来调用所选的解除分配函数,并且(如果两个使用块参数释放功能)块的大小作为其第二个参数。

5.3.5 Delete [expr.delete]

[...]
11 When a delete-expression is executed, the selected deallocation function shall be called with the address of the block of storage to be reclaimed as its first argument and (if the two-parameter deallocation function is used) the size of the block as its second argument.83

脚注83)如果要删除的对象的静态类型完成,不同于动态类型,析构函数不是
virtual,大小可能不正确,但是这种情况已经是未定义的,如上所述。

Footnote 83) If the static type of the object to be deleted is complete and is different from the dynamic type, and the destructor is not virtual, the size might be incorrect, but that case is already undefined, as stated above.






17.6.4.6替​​换函数 [replacement.functions]



1第18至30条和附录D描述了C ++标准库定义的许多函数的行为。然而,在某些情况下,这些函数描述中的某些也适用于程序(17.3)中定义的替换函数。

2一个C ++程序可以提供12个动态内存分配函数签名的定义< new> (3.7.4,18.6):

17.6.4.6 Replacement functions [replacement.functions]

1 Clauses 18 through 30 and Annex D describe the behavior of numerous functions defined by the C++ standard library. Under some circumstances, however, certain of these function descriptions also apply to replacement functions defined in the program (17.3).
2 A C++ program may provide the definition for any of twelve dynamic memory allocation function signatures declared in header <new> (3.7.4, 18.6):

operator new(std::size_t)
operator new(std::size_t, const std::nothrow_t&)
operator new[](std::size_t)
operator new[](std::size_t, const std::nothrow_t&)
perator delete(void*)
operator delete(void*, const std::nothrow_t&)
operator delete[](void*)
operator delete[](void*, const std::nothrow_t&)


我注意到:接下来的四个是C ++ 1y中的新

note by me: The next four are new in C++1y


operator delete(void*, std::size_t)
operator delete(void*, std::size_t, const std::nothrow_t&)
operator delete[](void*, std::size_t)
operator delete[](void*, std::size_t, const std::nothrow_t&)

3使用程序的定义来代替实现(18.6)提供的默认版本。这种替换发生在程序启动之前(3.2,3.6)。程序的定义不应被指定为内联。

3 The program’s definitions are used instead of the default versions supplied by the implementation (18.6). Such replacement occurs prior to program startup (3.2, 3.6). The program’s definitions shall not be specified as inline. No diagnostic is required.

另请参阅在C ++ 1y中引入大小重新分配的提议:

http://www.open-std .org / JTC1 / SC22 / WG21 / docs / papers / 2013 / n3536.html

Also take a look at the proposal which introduces sized deallocation in C++1y:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3536.html

这篇关于操作员删除签名意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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