動的割り当てが必要になるのは、オブジェクトのライフタイムが作成されたスコープとは異なる必要がある場合(これは、スコープを小さくする場合にも適用されます)に値で格納しないという特定の理由がある場合です作業。
例えば:
std::vector<int> *createVector(); // Bad
std::vector<int> createVector(); // Good
auto v = new std::vector<int>(); // Bad
auto result = calculate(/*optional output = */ v);
auto v = std::vector<int>(); // Good
auto result = calculate(/*optional output = */ &v);
C ++ 11以降、std::unique_ptr
割り当てられたメモリの所有権を含む割り当てられたメモリを処理する必要があります。std::shared_ptr
所有権を共有する必要がある場合のために作成されました。(これは、優れたプログラムで期待するよりも少なくて済みます)
インスタンスの作成は非常に簡単になります。
auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11
C ++ 17 std::optional
は、メモリ割り当てを必要としないようにすることもできます。
auto optInstance = std::optional<Class>{};
if (condition)
optInstance = Class{};
「インスタンス」が範囲外になるとすぐに、メモリはクリーンアップされます。所有権の譲渡も簡単です。
auto vector = std::vector<std::unique_ptr<Interface>>{};
auto instance = std::make_unique<Class>();
vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)
それで、いつあなたはまだ必要new
ですか?C ++ 11以降ではほとんどありません。std::make_unique
生のポインタを介して所有権を転送するAPIに到達するまでに使用するもののほとんど。
auto instance = std::make_unique<Class>();
legacyFunction(instance.release()); // Ownership being transferred
auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr
C ++ 98/03では、手動でメモリ管理を行う必要があります。この場合は、より新しいバージョンの標準にアップグレードしてください。行き詰まっている場合:
auto instance = new Class(); // Allocate memory
delete instance; // Deallocate
auto instances = new Class[42](); // Allocate memory
delete[] instances; // Deallocate
メモリリークが発生しないように、所有権を正しく追跡していることを確認してください。移動セマンティクスもまだ機能しません。
では、C ++でmallocが必要になるのはいつですか?唯一の有効な理由は、メモリを割り当て、後でnewを配置して初期化することです。
auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
auto instance = new(instanceBlob)Class{}; // Initialize via constructor
instance.~Class(); // Destroy via destructor
std::free(instanceBlob); // Deallocate the memory
上記は有効ですが、これはnew-operatorを介して行うこともできます。std::vector
これは良い例です。
最後に、部屋にはまだ象がいますC
。メモリがC ++コードで割り当てられ、Cコードで解放される(またはその逆)Cライブラリを使用する必要がある場合は、malloc / freeを使用する必要があります。
この場合は、仮想関数、メンバー関数、クラスを忘れてください... PODを含む構造体のみが許可されます。
ルールのいくつかの例外:
- mallocが適切な場合に、高度なデータ構造を持つ標準ライブラリを作成している
- 大量のメモリを割り当てる必要があります(10GBファイルのメモリコピーでは?)
- 特定の構成要素を使用できないツールがあります
- 不完全なタイプを保存する必要があります