Namespaces
Variants

operator new , operator new[]

From cppreference.net
< cpp ‎ | memory ‎ | new
Utilities library
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
**翻訳結果:** **説明:** - HTMLタグ、属性、C++コード(` `内)は一切翻訳していません - C++固有の用語(`void`, `operator new`, `std::size_t`など)は原文のまま保持しています - 数値の"(1)"も翻訳対象外としています - 元の書式と構造を完全に維持しています **翻訳結果:** **説明:** - HTMLタグ、属性、C++コード(` `内)はすべて原文のまま保持されています - 翻訳対象のテキスト部分が存在しないため、全体がそのまま出力されています - C++のキーワード(`void`、`operator new`、`std::size_t`など)は翻訳されていません - 数値の"(2)"もそのまま保持されています **翻訳結果:** **説明:** - HTMLタグ、属性、C++コード(` `内)は翻訳せず保持 - バージョン番号「(16)」はそのまま保持 - C++のキーワード(`void`, `operator`, `new`, `std::size_t`など)は翻訳せず保持 - 元のフォーマットと構造を完全に維持 (注:このHTML要素には翻訳対象となるテキストコンテンツが含まれていません。すべてのHTMLタグと属性は原文のまま保持されています。)
定義済みヘッダー <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-8) 置換可能 なアロケート関数。標準ライブラリはこれらの関数に対するデフォルト実装を提供しており、デフォルト実装の効果については 以下 を参照。
9,10) 標準の プレースメント new によって呼び出される。何も行わず、 ptr を変更せずに返す。
この関数が配置 new を通じて呼び出され、 ptr がヌルポインタの場合、動作は未定義です。
11-22) new式によって呼び出されるユーザー定義アロケーション関数。

オーバーロード ( 1-4 ) は、たとえ <new> ヘッダーがインクルードされていない場合でも、各翻訳単位で暗黙的に宣言されます。

オーバーロードの選択基準については、 new expression を参照してください。

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - C++関連の専門用語(Parameters、Return value、Exceptions、Global replacements、Class-specific overloads、Notes、Defect reports、References、See also)は原文のまま保持しました - HTMLタグ、属性、クラス名、ID、リンク先は一切変更していません - 数値や書式設定は完全に保持されています

パラメータ

count - 割り当てるバイト数
ptr - オブジェクトを初期化するメモリ領域へのポインタ
tag - 非スローオーバーロードを選択するための区別タグ
al - 使用するアライメント、無効な値は未定義動作を引き起こす

戻り値

1-4) メモリ確保が成功した場合、非ヌルポインタ p0 を返す。このポインタは少なくとも size バイトの適切にアラインされたメモリ領域を指し、かつ以前に返された値 p1 とは異なる(ただし、その値 p1 がその後 解放関数 に渡された場合は除く)。メモリ確保が失敗した場合は戻らない(例外がスローされる。詳細は後述)。
5-8) 以下は ( 1-4 ) と同じですが、メモリ確保に失敗した場合はヌルポインタを返します。
9,10) ptr
11-22) 割り当て失敗時に戻らない場合は ( 1-4 ) と同じ、それ以外の場合は ( 5-8 ) と同じ。

例外

1-4) メモリの割り当てに失敗した場合、 std::bad_alloc 型のハンドラに一致する型の例外をスローします。
11-22) 割り当て失敗時に戻らない場合は ( 1-4 ) と同じ、それ以外の場合は ( 5-8 ) と同じ。

グローバル置換

オーバーロード ( 1-8 ) 置換可能 です。デフォルトバージョンの効果は以下の通りです:

1) 要求されたストレージの割り当てを試みます。この試みが std::malloc または std::aligned_alloc の呼び出しを含むかどうかは未規定です。
  • 試みが成功した場合、割り当てられたストレージへのポインタを返します。
  • それ以外の場合、現在 new-handler がインストールされていない場合は、 std::bad_alloc をスローします。
  • それ以外の場合、現在インストールされているnew-handlerを呼び出します。
    • new-handlerが戻った場合、別の割り当て試行を開始します。
    • それ以外の場合、現在の呼び出しを終了します。
2) 返り値 operator new ( count )
3) (1) と同じ。
4) 返り値 operator new ( count, al ) .
5-8) それぞれ (1-4) を、以下の例外を除いて同じ引数で呼び出します: tag
  • 呼び出しが正常に戻った場合、その呼び出しの結果を返します。
  • それ以外の場合、ヌルポインタを返します。

フリースタンディング実装 において、デフォルトバージョンの ( 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 [ ]
  1. 形式的には、このマクロは 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メンバー関数)
解放関数
(関数)
現在のnewハンドラを取得する
(関数)
新しいハンドラを登録する
(関数)
(C++17で非推奨) (C++20で削除)
初期化されていないストレージを取得する
(関数テンプレート)
メモリを割り当てる
(関数)
アライメントされたメモリを割り当てる
(関数)