サーチ…
構文
- ::( OPT)新( 表現リスト )(OPT) 新型-ID、 新たな初期化子 (OPT)
- :( opt )new( 式リスト )( opt )( タイプID ) new-initializer ( opt )
- ::( opt ) キャスト式を削除する
- ::( opt )delete [] キャスト式
- std :: unique_ptr < type-id > var_name(新しいタイプ -id( opt )); // C ++ 11
- std :: shared_ptr < タイプID > var_name(新しいタイプ -id( opt )); // C ++ 11
- std :: shared_ptr < タイプID > var_name = std :: make_shared < タイプID >( opt ); // C ++ 11
- std :: unique_ptr < type-id > var_name = std :: make_unique < タイプID >( opt ); // C ++ 14
備考
leading ::
は、オーバーロードされたクラス固有の新規または削除演算子をオーバーライドして、new演算子またはdelete演算子をグローバルスコープで検索させます。
new
キーワードの後のオプションの引数は、通常、 配置newを呼び出すために使用されますが、選択されたプールからメモリを割り当てることを要求するタグなど、追加情報をアロケータに渡すためにも使用できます。
割り当てられた型は、通常、 new Foo
に明示的に指定されますが、 auto
(C ++ 11以降)またはdecltype(auto)
(C ++ 14以降)として初期化子から推論することもできます。
割り当てられたオブジェクトの初期化は、ローカル変数の初期化と同じ規則に従って行われます。特に、イニシャライザが省略された場合、オブジェクトはデフォルトで初期化され、スカラー型またはスカラー型の配列を動的に割り当てる場合、メモリがゼロになるという保証はありません。
new-expressionで作成された配列オブジェクトは、 new-expressionが[]
書かれているかどうかにかかわらず、 delete[]
を使ってdelete[]
必要があります。例えば:
using IA = int[4];
int* pIA = new IA;
delete[] pIA; // right
// delete pIA; // wrong
スタック
スタックは、実行中に一時的な値が格納される小さなメモリ領域です。スタックにデータを割り当てることは、すべてのメモリがすでにこの目的のために割り当てられているため、ヒープ割り当てに比べて非常に高速です。
int main() {
int a = 0; //Stored on the stack
return a;
}
スタックの名前は、関数呼び出しの連鎖がメモリの別々の小さなセクションを使用してそれぞれの上に「スタック」された一時的なメモリを持つために名前が付けられます。
float bar() {
//f will be placed on the stack after anything else
float f = 2;
return f;
}
double foo() {
//d will be placed just after anything within main()
double d = bar();
return d;
}
int main() {
//The stack has no user variables stored in it until foo() is called
return (int)foo();
}
スタックに格納されたデータは、変数を割り当てたスコープがまだアクティブである限り有効です。
int* pA = nullptr;
void foo() {
int b = *pA;
pA = &b;
}
int main() {
int a = 5;
pA = &a;
foo();
//Undefined behavior, the value pointed to by pA is no longer in scope
a = *pA;
}
フリーストレージ(ヒープ、動的割り当て...)
用語「ヒープ」は、 スタックが提供するメモリとは独立して、部分を割り振りおよび割り振り解除できるメモリ領域を意味する一般的な計算用語です。
C++
、この標準は、より正確な用語と見なされるフリーストアとして参照されています。
フリーストアから割り当てられたメモリ領域は、割り当てられた元のスコープより長く存続することがあります。スタックに格納するには大きすぎるデータは、 Free Storeから割り当てられることもあります。
生メモリは、 新しいキーワードと削除するキーワードによって割り当てられたり、割り当て解除されたりすることができます。
float *foo = nullptr;
{
*foo = new float; // Allocates memory for a float
float bar; // Stack allocated
} // End lifetime of bar, while foo still alive
delete foo; // Deletes the memory for the float at pF, invalidating the pointer
foo = nullptr; // Setting the pointer to nullptr after delete is often considered good practice
固定サイズの配列をnewとdeleteで割り振ることも可能で、構文も少し異なります。配列の割り当ては配列以外の割り当てと互換性がなく、2つを混在させるとヒープの破損につながります。配列を割り当てることは、後で実装定義の方法で削除するために、配列のサイズを追跡するためにメモリを割り当てます。
// Allocates memory for an array of 256 ints
int *foo = new int[256];
// Deletes an array of 256 ints at foo
delete[] foo;
newを使用し、 mallocとfreeの代わりにdeleteを使用する と 、コンストラクタとデストラクタが実行されます(スタックベースのオブジェクトと同様)。これは、 mallocとfreeよりも新しい 、 deleteを好む理由です。
struct ComplexType {
int a = 0;
ComplexType() { std::cout << "Ctor" << std::endl; }
~ComplexType() { std::cout << "Dtor" << std::endl; }
};
// Allocates memory for a ComplexType, and calls its constructor
ComplexType *foo = new ComplexType();
//Calls the destructor for ComplexType() and deletes memory for a Complextype at pC
delete foo;
C ++ 11以降では、所有権を示すためにスマートポインタを使用することをお勧めします。
C ++ 14では、 std::make_unique
をSTLに追加し、ネイキッドnewとdeleteを使用するのではなく、 std::make_unique
またはstd::make_shared
推奨するように変更しました。
プレースメント新しい
メモリを割り当てるためにFree Storeに依存したくない状況があり、 new
メモリを使用してカスタムメモリ割り当てを使用したい場合があります。
このような状況では、 Placement New
を使用することができます。ここでは、「new」演算子に、事前に割り当てられたメモリ位置からメモリを割り当てるよう指示できます
例えば
int a4byteInteger;
char *a4byteChar = new (&a4byteInteger) char[4];
この例では、 a4byteChar
が指すメモリは、整数変数a4byteInteger
介して 'stack'に割り当てられた4バイトa4byteInteger
。
この種のメモリ割り当ての利点は、プログラマが割り当てを制御するという事実です。上記の例では、 a4byteInteger
はスタック上に割り当てられているので、 'delete a4byteChar`を明示的に呼び出す必要はありません。
ダイナミックに割り当てられたメモリに対しても同様の動作が得られます。例えば
int *a8byteDynamicInteger = new int[2];
char *a8byteChar = new (a8byteDynamicInteger) char[8];
この場合、によってメモリ・ポインタa8byteChar
によって割り当てられた動的メモリを参照するa8byteDynamicInteger
。しかし、この場合、 delete a8byteDynamicInteger
を明示的に呼び出してメモリを解放delete a8byteDynamicInteger
必要があります
C ++クラスの別の例
struct ComplexType {
int a;
ComplexType() : a(0) {}
~ComplexType() {}
};
int main() {
char* dynArray = new char[256];
//Calls ComplexType's constructor to initialize memory as a ComplexType
new((void*)dynArray) ComplexType();
//Clean up memory once we're done
reinterpret_cast<ComplexType*>(dynArray)->~ComplexType();
delete[] dynArray;
//Stack memory can also be used with placement new
alignas(ComplexType) char localArray[256]; //alignas() available since C++11
new((void*)localArray) ComplexType();
//Only need to call the destructor for stack memory
reinterpret_cast<ComplexType*>(localArray)->~ComplexType();
return 0;
}