導入
C++でのメモリ管理において、std::unique_ptrは所有権を明確にし、メモリリークを防ぐための強力なツールです。しかし、ファクトリ関数などで「条件によってオブジェクトを生成するか、あるいは何も返さない(nullptr)」という状況に直面することは少なくありません。本記事では、std::unique_ptrを条件付きで安全かつ簡潔に生成するテクニックを解説します。
基礎知識
std::unique_ptrは、動的に確保されたオブジェクトの所有権を独占するスマートポインタです。このポインタがスコープを抜けると、自動的にdeleteが呼び出され、メモリが解放されます。
通常、std::make_uniqueを使用して生成しますが、条件次第で「生成しない(無効なポインタを返す)」という処理が必要になる場合があります。ここで重要なのが、std::unique_ptrはnullptrを代入することで「何も持っていない状態」を表現できるという点です。
実装/解決策
条件付き生成を行う際は、if文による早期リターンを利用するのが最も可読性が高く効率的です。条件式が偽(失敗)であればnullptrを返し、真であればstd::make_uniqueを呼び出してオブジェクトを生成します。これにより、不要なコンストラクタの呼び出しを避け、コードの意図を明確にできます。
サンプルプログラム
以下のコードは、条件に応じてオブジェクトを生成するファクトリ関数の例です。
include
include
include
// サンプル用クラス
class Product {
public:
Product(std::string name) : name_(name) {}
void show() { std::cout << "製品名: " << name_ << std::endl; }
private:
std::string name_;
};
// ファクトリ関数:条件に応じてunique_ptrを生成
std::unique_ptr
// 条件が満たされない場合はnullptrを返して終了
if (!is_valid) {
return nullptr;
}
// 条件を満たす場合のみメモリを確保して生成
return std::make_unique
}
int main() {
auto p1 = createProduct(true);
if (p1) {
p1->show();
} else {
std::cout << "生成失敗" << std::endl;
}
auto p2 = createProduct(false);
if (!p2) {
std::cout << "p2は空です" << std::endl;
}
return 0;
}
応用・注意点
注意点1:例外安全性の確保
std::make_uniqueは、コンストラクタで例外が発生した場合でもメモリリークを起こさないように設計されています。条件分岐の中で直接newを使うのではなく、可能な限りstd::make_uniqueを使用することを推奨します。
注意点2:std::optionalの検討
もし「オブジェクトが存在しないこと」がエラーではなく、単なる状態の一つである場合は、C++17以降であればstd::optional
現場のヒント
複雑な条件分岐が続く場合は、ガード句(早期リターン)を徹底することで、ネストを深くせずコードの可読性を保つことができます。ぜひプロジェクトの設計に取り入れてみてください。

コメント