operators (delete[])
操作符删除,操作符删除。[]
Defined in header | | |
---|---|---|
replaceable usual deallocation functions | | |
void operator delete ( void* ptr | (1) | |
void operator delete; | (2) | |
void operator delete ( void* ptr, std::align_val_t al | (3) | (since C++17) |
void operator delete; | (4) | (since C++17) |
void operator delete ( void* ptr, std::size_t sz | (5) | (since C++14) |
void operator delete; | (6) | (since C++14) |
void operator delete ( void* ptr, std::size_t sz, std::align_val_t al | (7) | (since C++17) |
void operator delete; | (8) | (since C++17) |
replaceable placement deallocation functions | | |
void operator delete ( void* ptr, const std::nothrow_t& tag | (9) | |
void operator delete; | (10) | |
void operator delete ( void* ptr, std::align_val_t al, const std::nothrow_t& tag | (11) | (since C++17) |
void operator delete; | (12) | (since C++17) |
non-allocating placement deallocation functions | | |
void operator delete ( void* ptr, void* place | (13) | |
void operator delete; | (14) | |
user-defined placement deallocation functions | | |
void operator delete ( void* ptr, args... | (15) | |
void operator delete; | (16) | |
class-specific usual deallocation functions | | |
void T::operator delete ( void* ptr | (17) | |
void T::operator delete; | (18) | |
void T::operator delete ( void* ptr, std::align_val_t al | (19) | (since C++17) |
void T::operator delete; | (20) | (since C++17) |
void T::operator delete ( void* ptr, std::size_t sz | (21) | |
void T::operator delete; | (22) | |
void T::operator delete ( void* ptr, std::size_t sz, std::align_val_t al | (23) | (since C++17) |
void T::operator delete; | (24) | (since C++17) |
class-specific placement deallocation functions | | |
void T::operator delete ( void* ptr, args... | (25) | |
void T::operator delete; | (26) | |
分配以前由匹配分配的存储空间。operator new
.这些取消分配功能由删除-表达式并通过新表达式若要在解构%28之后释放内存,或未能构造具有动态存储持续时间的%29对象,请执行以下操作。它们也可以使用常规函数调用语法进行调用。
1%29删除-表达式若要释放先前为单个对象分配的存储,请执行以下操作。此函数的标准库实现的行为是未定义的,除非ptr
的标准库实现中获得的指针。operator new
(size_t)
或operator new
(size_t,
std::nothrow_t
)
...
2%29删除。[]---表达方式若要释放以前分配给对象数组的存储,请执行以下操作。此函数的标准库实现的行为是未定义的,除非ptr
的标准库实现中获得的指针。operator new
[](size_t)
或operator new
[](size_t,
std::nothrow_t
)
...
3.4%29与%281 2%29相同,但如果对齐要求超过__STDCPP_DEFAULT_NEW_ALIGNMENT__
如果提供了用户定义的替换,则调用5-6%29而不是%281-2%29,除非在删除不完全类型的对象和非类数组以及非类数组和可销毁类类型的数组%28自C++17%29时,它定义的%27s实现是否调用%281-2%29或%285-6%29。内存分配器可以使用给定的大小来提高效率。标准库实现与%281-2%29相同.
7-8%29与%285-6%29相同,但如果对齐要求超过__STDCPP_DEFAULT_NEW_ALIGNMENT__
9%29由非抛出的单一对象调用。新表达式如果对象的构造函数抛出异常。标准库实现的行为与%281%29相同。
10%29由非抛出数组调用。新。[]---表达方式如果任何对象的构造函数在执行已成功构造的数组中的所有对象的析构函数后抛出异常%28,则为%29。标准库实现的行为与%282%29相同。
11,12%29与%289,10%29相同,但如果对齐要求超过__STDCPP_DEFAULT_NEW_ALIGNMENT__
标准单对象调用的13%29安置新如果对象%27s构造函数抛出异常,则表示。此函数的标准库实现不起任何作用。
的标准数组形式调用的14%29安置新表达式,如果任何对象%27构造函数在执行所有已成功构造的对象的析构函数后抛出异常%28。此函数的标准库实现不起任何作用。
15%29如果定义了,则由自定义单个对象调用。安置新如果对象%27s构造函数抛出异常,则具有匹配签名的表达式。如果定义了特定于类的版本%2825%29,则优先调用它而不是%289%29.。如果用户既不提供%2825%29,也不提供%2815%29,则不调用解分配函数。
16%29如果定义了,则由自定义数组形式调用安置新。[]如果任何对象%27构造函数在为所有已成功构造的对象执行析构函数后抛出异常%28,则具有匹配签名的表达式。如果定义了特定于类的版本%2816%29,则优先调用它而不是%2810%29.。如果用户既不提供%2826%29,也不提供%2816%29,则不调用任何释放函数。
17%29如果定义为普通的单对象调用删除-表达式如果释放类型为T的对象。
18%29如果定义了,则由通常的数组调用。删除。[]---表达方式如果释放类型为T的对象数组。
19,20%29,如果定义,优先调用%2817,18%29,如果对齐要求超过__STDCPP_DEFAULT_NEW_ALIGNMENT__
...
21%29如果定义了,如果%2817%29未定义,则由通常的单个对象调用。删除-表达式如果释放类型为T的对象。
22%29如果定义了,如果没有定义%2818%29,则由通常的数组调用删除。[]---表达方式如果释放类型为T的对象数组。
如果定义了23,24%29,如果%2819,20%29未定义,则优先调用分配程序-如果对齐要求超过,则不知道成员。__STDCPP_DEFAULT_NEW_ALIGNMENT__
...
25%29如果定义了,则由自定义单个对象调用。安置新如果对象%27s构造函数抛出异常,则具有匹配签名的表达式。如果未提供此函数,并且也未提供匹配的%2815%29,则不调用任何解除分配函数。
26%29如果定义了,则由自定义数组形式调用安置新。[]如果任何对象%27构造函数在为所有已成功构造的对象执行析构函数后抛出异常%28,则具有匹配签名的表达式。如果未提供此函数,并且也未提供匹配的%2816%29,则不调用任何解除分配函数。
See delete-expression for exact details on the overload resolution rules between alignment-aware and alignment-unaware overloads of usual (non-placement) deallocation functions. | (since C++17) |
---|
在所有情况下,如果ptr
是一个空指针,标准库的去分配函数什么也不做。如果没有从相应的标准库分配函数中获得传递到标准库去分配函数的指针,则该行为是未定义的。
在标准库解分配函数返回后,引用已分配存储的任何部分的所有指针都将无效。
Any use of a pointer that became invalid in this manner, even copying the pointer value into another variable, is undefined behavior. | (until C++14) |
---|---|
Indirection through a pointer that became invalid in this manner and passing it to a deallocation function (double-delete) is undefined behavior. Any other use is implementation-defined. | (since C++14) |
参数
ptr | - | pointer to a memory block to deallocate or a null pointer |
---|---|---|
sz | - | the size that was passed to the matching allocation function |
place | - | pointer used as the placement parameter in the matching placement new |
tag | - | overload disambiguation tag matching the tag used by non-throwing operator new |
al | - | alignment of the object or array element that was allocated |
args | - | arbitrary parameters matching a placement allocation function (may include std::size_t and std::align_val_t) |
返回值
%280%29
例外
(none) | (until C++11) |
---|---|
noexcept specification: noexcept | (since C++11) |
全局替换
可替换的可取消分配函数%281-10%29在每个转换单元中被隐式声明,即使<new>不包括标头。这些功能是可替换:用户提供的具有相同签名的非成员函数,在程序的任何地方,在任何源文件中,替换整个程序的相应隐式版本。它的声明不需要是可见的。
如果程序中提供了多个替换,或者使用inline
说明符,如果替换在全局命名空间以外的名称空间中定义,或者在全局范围内定义为静态非会员函数,则程序的格式不正确。
The standard library implementations of the nothrow versions (9,10) directly call the corresponding throwing versions (1,2). The standard library implementations of the size-aware deallocation functions (5-8) directly call the corresponding size-unaware deallocation functions (1-4). The standard library implementations of size-unaware throwing array forms (2,4) directly calls the corresponding single-object forms (1,3). Thus, replacing the throwing single object deallocation functions (1,3) is sufficient to handle all deallocations. | (since C++11) |
---|
二次
#include <cstdio>
#include <cstdlib>
// replacement of a minimal set of functions:
void* operator new(std::size_t sz) {
std::printf("global op new called, size = %zu\n",sz
return std::malloc(sz
}
void operator delete(void* ptr) noexcept
{
std::puts("global op delete called"
std::free(ptr
}
int main() {
int* p1 = new int;
delete p1;
int* p2 = new int[10]; // guaranteed to call the replacement in C++11
delete[] p2;
}
二次
可能的产出:
二次
global op new called, size = 4
global op delete called
global op new called, size = 40
global op delete called
二次
超载operator delete
和operator delete[]
对于附加的用户定义参数%28“放置表单”,%2815 16%29%5月29日将像往常一样在全局范围内声明,并由匹配的布局表单调用。新表达式
如果要分配的对象的构造函数抛出异常。
运算符删除%2813 14%29的标准库放置表单不能被替换,只有在新的放置表达式没有使用::new
语法,通过提供具有匹配签名的类特定位置删除%2825 26%29:void T::operator delete(void*, void*)
或void T::operator delete[](void*, void*)
...
All deallocation functions are noexcept(true) unless specified otherwise in the declaration. | (since C++11) |
---|
类特定重载
5月29日,解除分配函数%2817-24%被定义为类的静态成员函数。如果提供这些解除分配函数,则由删除-表达式删除对象%2817,19,21%29和数组%2818,20,22%29时,除非DELETE表达式使用该窗体::delete
它绕过了类范围查找。关键词static
对于这些函数声明是可选的:无论是否使用关键字,de配函数始终是静态成员函数。
DELETE表达式从类作用域%28数组表单开始查找适当的去分配函数%27s名称,查找数组元素类%29的作用域,如果没有像往常一样找到成员,则继续执行全局范围。注意,按名称查找规则,类范围中声明的任何去分配函数都会隐藏所有全局退分配函数。
如果要删除的对象的静态类型与其动态类型%28不同,例如当删除多态通过指向基%29的指针,如果静态类型中的析构函数是虚拟的,则删除的单个对象形式开始查找从其虚拟析构函数的最终覆盖程序的定义开始的解除分配函数%27 s的名称。无论在运行时执行哪一种去分配函数,都必须访问静态可见的操作符DELETE版本才能编译。在其他情况下,当通过指向基的指针删除数组时,或者当使用非虚拟析构函数删除“从指针到基”时,行为是未定义的。
如果没有提供单参数重载%2817,18%29,但是大小感知重载。std::size_t
由于提供了第二个参数%2821,22%29,因此调用了正常去分配的大小感知表单,C++运行时将要释放的对象的大小作为第二个参数传递。如果定义了这两种表单,则调用不知道大小的版本。
二次
#include <iostream>
// sized class-specific deallocation functions
struct X {
static void operator delete(void* ptr, std::size_t sz)
{
std::cout << "custom delete for size " << sz << '\n';
::operator delete(ptr
}
static void operator delete[](void* ptr, std::size_t sz)
{
std::cout << "custom delete for size " << sz << '\n';
::operator delete(ptr
}
};
int main() {
X* p1 = new X;
delete p1;
X* p2 = new X[10];
delete[] p2;
}
二次
可能的产出:
二次
custom delete for size 1
custom delete for size 18
二次
超载operator delete
和operator delete[]
对于其他用户定义的参数%28“放置表单”,%2825,26%29%5月29日也被定义为类成员。当失败的放置新表达式查找要调用的相应的放置删除函数时,它将在检查全局作用域之前开始查找类作用域,并使用匹配布局新的签名查找函数:
二次
#include <stdexcept>
#include <iostream>
struct X {
X() { throw std::runtime_error("" }
// custom placement new
static void* operator new(std::size_t sz, bool b) {
std::cout << "custom placement new called, b = " << b << '\n';
return ::operator new(sz
}
// custom placement delete
static void operator delete(void* ptr, bool b)
{
std::cout << "custom placement delete called, b = " << b << '\n';
::operator delete(ptr
}
};
int main() {
try {
X* p1 = new (true) X;
} catch(const std::exception&) { }
}
二次
产出:
二次
custom placement new called, b = 1
custom placement delete called, b = 1
二次
IF级operator delete
是一个模板函数,它必须具有void
,第一个论点void*
,而且它必须有两个或两个以上的参数。换句话说,只有安置表格才能成为模板。模板操作符DELETE的专门化是使用模板参数推导...
注记
对类特定的调用。T::operator delete
在多态类上,只有通过动态分派调用静态成员函数的情况。
The following functions are required to be thread-safe: The library versions of operator new and operator delete User replacement versions of global operator new and operator delete std::calloc, std::malloc, std::realloc, std::aligned_alloc (since C++17) Calls to these functions that allocate or deallocate a particular unit of storage occur in a single total order, and each such deallocation call happens-before the next allocation (if any) in this order. | (since C++11) |
---|
- 的库版本
operator new
和operator delete
- 全局用户替换版本
operator new
和operator delete
std::calloc
,,,std::malloc
,,,std::realloc
,,,std::aligned_alloc
%28自C++17%29
对分配或释放特定存储单元的这些函数的调用是以单个总顺序进行的,并且每个这样的释放调用都会发生。发生-之前下一次按此顺序分配%28(如果有%29)。
%28自C++11%29
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2458 | C++14 | overloads taking (void*,size_t,const nothrow_t&) were specified, but could never be called | spurious overloads removed |
另见
operator newoperator new[] | allocation functions (function) |
---|---|
return_temporary_buffer | releases uninitialized storage (function) |
free | deallocates memory (function) |
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。