operator new , operator new[]
|
定義済みヘッダー
<new>
|
||
|
置換可能なアロケーション関数
|
||
|
void
*
operator new
(
std::
size_t
count
)
;
|
(1) | |
|
void
*
operator new
(
std::
size_t
count
)
;
|
(1) | |
|
void
*
operator new
[
]
(
std::
size_t
count
)
;
|
(2) | |
|
void
*
operator new
[
]
(
std::
size_t
count
)
;
|
(2) | |
|
void
*
operator new
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(3) | (C++17以降) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(4) | (C++17以降) |
|
置換可能な例外を投げないアロケート関数
|
||
|
void
*
operator new
(
std::
size_t
count,
const
std::
nothrow_t
&
tag
)
;
|
(5) | (C++11以降noexcept) |
|
void
*
operator new
[
]
(
std::
size_t
count,
const
std::
nothrow_t
&
tag
)
;
|
(6) | (C++11以降 noexcept) |
|
void
*
operator new
(
std::
size_t
count,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(7) | (C++17以降) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(8) | (C++17以降) |
|
メモリ割り当てを行わない配置new関数
|
||
|
void
*
operator new
(
std::
size_t
count,
void
*
ptr
)
;
|
(9) |
(C++11以降noexcept)
(C++26以降constexpr) |
|
void
*
operator new
[
]
(
std::
size_t
count,
void
*
ptr
)
;
|
(10) |
(C++11以降 noexcept)
(C++26以降 constexpr) |
|
ユーザー定義配置アロケーション関数
|
||
|
void
*
operator new
(
std::
size_t
count,
/* 引数... */
)
;
|
(11) | |
|
void
*
operator new
[
]
(
std::
size_t
count,
/* 引数... */
)
;
|
(12) | |
|
void
*
operator new
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(13) | (C++17以降) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(14) | (C++17以降) |
|
クラス固有のアロケーション関数
|
||
|
void
*
T
::
operator
new
(
std::
size_t
count
)
;
|
(15) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count
)
;
|
(16) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count
)
;
|
(16) | |
|
void
*
T
::
operator
new
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(17) | (C++17以降) |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(18) | (C++17以降) |
|
クラス固有の配置アロケーション関数
|
||
|
void
*
T
::
operator
new
(
std::
size_t
count,
/* 引数... */
)
;
|
(19) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
/* 引数... */
)
;
|
(20) | |
|
void
*
T
::
operator
new
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(21) | (C++17以降) |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
std:: align_val_t al, /* 引数... */ ) ; |
(22) | (C++17以降) |
要求されたバイト数の割り当てを試み、割り当て要求は失敗する可能性があります(要求されたバイト数がゼロの場合でも)。これらの割り当て関数は、 new 式 によって呼び出され、新しいオブジェクトが初期化されるメモリを割り当てます。また、通常の関数呼び出し構文を使用して呼び出すこともできます。
オーバーロード ( 1-4 ) は、たとえ <new> ヘッダーがインクルードされていない場合でも、各翻訳単位で暗黙的に宣言されます。
オーバーロードの選択基準については、 new expression を参照してください。
目次 |
パラメータ
| count | - | 割り当てるバイト数 |
| ptr | - | オブジェクトを初期化するメモリ領域へのポインタ |
| tag | - | 非スローオーバーロードを選択するための区別タグ |
| al | - | 使用するアライメント、無効な値は未定義動作を引き起こす |
戻り値
例外
グローバル置換
オーバーロード ( 1-8 ) は 置換可能 です。デフォルトバージョンの効果は以下の通りです:
- 試みが成功した場合、割り当てられたストレージへのポインタを返します。
- それ以外の場合、現在 new-handler がインストールされていない場合は、 std::bad_alloc をスローします。
-
それ以外の場合、現在インストールされているnew-handlerを呼び出します。
- new-handlerが戻った場合、別の割り当て試行を開始します。
- それ以外の場合、現在の呼び出しを終了します。
- 呼び出しが正常に戻った場合、その呼び出しの結果を返します。
- それ以外の場合、ヌルポインタを返します。
|
フリースタンディング実装 において、デフォルトバージョンの ( 1-8 ) が上記で要求される動作を満たすかどうかは実装定義である。フリースタンディング実装では、これらのデフォルトバージョンのいずれかがホスト実装の要件を満たす場合、それらすべてが満たすことが推奨される。 |
(C++26以降) |
グローバル
operator
new
/
delete
の置き換え:
#include <cstdio> #include <cstdlib> #include <new> // no inline, required by [replacement.functions]/3 void* operator new(std::size_t sz) { std::printf("1) new(size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } // no inline, required by [replacement.functions]/3 void* operator new[](std::size_t sz) { std::printf("2) new[](size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } void operator delete(void* ptr) noexcept { std::puts("3) delete(void*)"); std::free(ptr); } void operator delete(void* ptr, std::size_t size) noexcept { std::printf("4) delete(void*, size_t), size = %zu\n", size); std::free(ptr); } void operator delete[](void* ptr) noexcept { std::puts("5) delete[](void* ptr)"); std::free(ptr); } void operator delete[](void* ptr, std::size_t size) noexcept { std::printf("6) delete[](void*, size_t), size = %zu\n", size); 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; }
出力例:
// Compiled with GCC-5 in C++17 mode to obtain the following: 1) op new(size_t), size = 4 4) op delete(void*, size_t), size = 4 2) op new[](size_t), size = 40 5) op delete[](void* ptr)
operator new
および
operator new[]
の追加のユーザー定義パラメータを持つオーバーロード(「配置形式」、バージョン
(
11-14
)
)は、通常通りグローバルスコープで宣言でき、対応する
配置形式
の
new
式によって呼び出されます。
標準ライブラリの非割り当て配置形式の
operator new
(
9,10
)
は置き換え不可能であり、配置
new
式が
::
new
構文を使用しなかった場合にのみ、一致するシグネチャを持つクラス固有の配置
new
(
19,20
)
を提供することでカスタマイズできます:
void
*
T
::
operator
new
(
std::
size_t
,
void
*
)
または
void
*
T
::
operator
new
[
]
(
std::
size_t
,
void
*
)
。
|
配置形式 void * operator new ( std:: size_t , std:: size_t ) は許可されていません。対応する解放関数のシグネチャ void operator delete ( void * , std:: size_t ) が通常の(配置形式ではない)解放関数であるためです。 |
(C++14以降) |
クラス固有のオーバーロード
単一オブジェクトと配列の両方のアロケート関数は、クラスの公開静的メンバ関数として定義できます(バージョン ( 15-18 ) )。定義されている場合、これらのアロケート関数は new 式によって、このクラスの単一オブジェクトと配列のメモリを確保するために呼び出されます。ただし、 new 式が :: new 形式を使用した場合は、クラススコープのルックアップをバイパスします。キーワード static はこれらの関数ではオプションです:使用するかどうかに関わらず、アロケート関数は静的メンバ関数です。
new 式はまずクラススコープで適切な割り当て関数の名前を探し、その後グローバルスコープで探します。 名前探索規則 に従い、クラススコープで宣言された割り当て関数は、このクラスのオブジェクトを割り当てようとする new 式に対するすべてのグローバルな割り当て関数を隠蔽することに注意してください。
|
アライメントが __STDCPP_DEFAULT_NEW_ALIGNMENT__ を超えるオブジェクトおよびオブジェクト配列を割り当てる際、オーバーロード解決は2回実行される:最初にアライメント対応の関数シグネチャに対して、次にアライメント非対応の関数シグネチャに対して行われる。これは、拡張アライメントを持つクラスがアライメント非対応のクラス固有の割り当て関数を持つ場合、グローバルなアライメント対応の割り当て関数ではなく、その関数が呼び出されることを意味する。これは意図的なものである:クラスメンバーはそのクラスを最も適切に扱う方法を知っていると期待される。 |
(C++17以降) |
|
__STDCPP_DEFAULT_NEW_ALIGNMENT__ を超えないアライメントを持つオブジェクトおよびオブジェクト配列を割り当てる場合、 オーバーロード解決は2回実行される:最初にアライメント非対応の関数シグネチャに対して、次にアライメント対応の関数シグネチャに対して行われる。 |
(C++20以降) |
#include <cstddef> #include <iostream> // クラス固有のアロケーション関数 struct X { static void* operator new(std::size_t count) { std::cout << "custom new for size " << count << '\n'; return ::operator new(count); } static void* operator new[](std::size_t count) { std::cout << "custom new[] for size " << count << '\n'; return ::operator new[](count); } }; int main() { X* p1 = new X; delete p1; X* p2 = new X[10]; delete[] p2; }
出力例:
custom new for size 1 custom new[] for size 10
追加のユーザー定義パラメータを持つ
operator new
および
operator new[]
のオーバーロード(「placement forms」)は、クラスメンバーとして定義することもできます
(
19-22
)
)。一致するシグネチャを持つplacement
new
式が呼び出す対応するアロケート関数を検索する際、グローバルスコープを調べる前にクラススコープから検索を開始し、クラス固有のplacement
new
が提供されている場合、それが呼び出されます。
|
アライメントが __STDCPP_DEFAULT_NEW_ALIGNMENT__ を超えるオブジェクトおよびオブジェクト配列を割り当てる場合、配置形式のオーバーロード解決は通常形式と同様に2回実行される:最初にアライメントを考慮する関数シグネチャに対して、次にアライメントを考慮しない関数シグネチャに対して行われる。 |
(C++17以降) |
|
アライメントが __STDCPP_DEFAULT_NEW_ALIGNMENT__ を超えないオブジェクトおよびオブジェクトの配列を割り当てる場合、配置形式のオーバーロード解決は通常の形式と同様に2回実行される:最初にアライメント非対応の関数シグネチャに対して、次にアライメント対応の関数シグネチャに対して行われる。 |
(C++20以降) |
#include <cstddef> #include <iostream> #include <stdexcept> struct X { X() { throw std::runtime_error(""); } // カスタム配置new static void* operator new(std::size_t count, bool b) { std::cout << "custom placement new called, b = " << b << '\n'; return ::operator new(count); } // カスタム配置delete static void operator delete(void* ptr, bool b) { std::cout << "custom placement delete called, b = " << b << '\n'; ::operator delete(ptr); } }; int main() { try { [[maybe_unused]] X* p1 = new (true) X; } catch (const std::exception&) {} }
出力:
custom placement new called, b = 1 custom placement delete called, b = 1
クラスレベルの
operator new
がテンプレート関数である場合、その戻り値の型は
void
*
でなければならず、第一引数は
std::size_t
で、2つ以上のパラメータを持たなければなりません。言い換えれば、配置形式のみがテンプレート化可能です。
注記
非割り当て配置 new ( 9,10 ) が置き換え不能であっても、前述のようにクラススコープで同じシグネチャを持つ関数を定義することができます。さらに、配置 new のように見えるが第二引数として非voidポインタ型を取るグローバルなオーバーロードが許可されているため、真の配置 new が呼び出されることを保証したいコード(例: std::allocator::construct )は、 :: new を使用し、さらにポインタを void * にキャストする必要があります。
解放関数の動作がデフォルトの制約を満たさない場合、その動作は未定義です。
|
以下の関数はスレッドセーフであることが要求されます:
特定の記憶単位を割り当てまたは解放するこれらの関数の呼び出しは、単一の全順序で発生し、それぞれの解放呼び出しは 先行発生 します(この順序における次の割り当て(もしあれば)に対して)。 |
(C++11以降) |
ライブラリバージョンの
operator new
が
std::malloc
または
std::aligned_alloc
(C++17以降)
を呼び出すかどうかは未規定です。
大容量ファイルの読み込みには、ファイル読み込み用のバッファを割り当てるよりも、OS固有の機能によるファイルマッピング、例えば
mmap
on POSIX または
CreateFileMapping
(
A
/
W
) と
MapViewOfFile
on Windows を使用する方が望ましいです。
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_freestanding_operator_new
|
202306L
|
(C++26) | 置き換え可能な operator new のフリースタンディング対応 [1] |
0
|
(C++26) | フリースタンディング対応なし | |
__cpp_lib_constexpr_new
|
202406L
|
(C++26) | constexpr 配置 new および new [ ] |
- ↑ 形式的には、このマクロは 202306L に展開されます。これは、置換可能なグローバル割り当て関数のデフォルトバージョンがすべて、ホスト環境実装の要件を満たしている場合です。
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 521 | C++98 |
std::bad_alloc
から派生した任意のクラスがスロー可能、
たとえ std::bad_alloc 基底クラスが曖昧またはアクセス不能であっても |
スローされる例外は
std::bad_alloc 型のハンドラにマッチすべき |
| LWG 9 | C++98 |
ゼロバイトの割り当てに対する複数回の呼び出しが
同じポインタを返す可能性があった |
以前に返されたすべてのそのようなポインタが
解放関数に渡されている場合にのみ許可される |
| LWG 206 | C++98 |
置換可能な割り当て関数の置き換えが
対応する置換可能な非スロー割り当て関数の デフォルト動作に影響を与えなかった |
デフォルト動作は
それに応じて変更される |
| LWG 404 | C++98 |
置換可能な割り当て関数の置き換えが
inline として宣言可能であった |
禁止、診断は不要 |
参考文献
- C++23標準 (ISO/IEC 14882:2024):
-
- 17.7 動的メモリ管理 [support.dynamic]
- C++20標準 (ISO/IEC 14882:2020):
-
- 17.6 動的メモリ管理 [support.dynamic]
- C++17 標準 (ISO/IEC 14882:2017):
-
- 21.6 動的メモリ管理 [support.dynamic]
- C++14 標準 (ISO/IEC 14882:2014):
-
- 18.6 動的メモリ管理 [support.dynamic]
- C++11標準 (ISO/IEC 14882:2011):
-
- 18.6 動的メモリ管理 [support.dynamic]
- C++03規格 (ISO/IEC 14882:2003):
-
- 18.4 動的メモリ管理 [lib.support.dynamic]
- C++98標準 (ISO/IEC 14882:1998):
-
- 18.4 動的メモリ管理 [lib.support.dynamic]
関連項目
|
[static]
(C++23)
|
Allocator
を使用してメモリを割り当てる
(
std::generator<Ref,V,Allocator>::promise_type
のpublic staticメンバー関数)
|
|
解放関数
(関数) |
|
|
(C++11)
|
現在のnewハンドラを取得する
(関数) |
|
新しいハンドラを登録する
(関数) |
|
|
(C++17で非推奨)
(C++20で削除)
|
初期化されていないストレージを取得する
(関数テンプレート) |
|
メモリを割り当てる
(関数) |
|
|
(C++17)
|
アライメントされたメモリを割り当てる
(関数) |