【C++学習|実務向け】実務で差がつく!std::unique_ptr を用いた安全な動的配列管理術

導入: なぜ unique_ptr の配列対応が重要なのか

C++の現場において、生ポインタ(raw pointer)によるメモリ管理はバグの温床です。特に配列を動的に確保した場合、解放忘れ(メモリリーク)や、間違えて delete を呼び出すことによる未定義動作が頻発します。C++11以降、std::unique_ptr を活用することで、スコープを抜ける際に自動的に delete[] が呼ばれるようになり、安全性が劇的に向上しました。本記事では、この配列対応の正しい使い方と注意点を解説します。

基礎知識: スマートポインタと配列の特殊化

通常、std::unique_ptr は delete を呼び出しますが、配列を扱う場合は delete[] が必要です。std::unique_ptr にはテンプレートの特殊化が用意されており、テンプレート引数に T[] を指定することで、内部的に自動で delete[] を使用するように切り替わります。これを利用することで、手動での解放処理を排除し、例外安全なコードを実現できます。

実装/解決策: std::make_unique の活用

C++14 から導入された std::make_unique を使用するのがベストプラクティスです。これにより、new[] 式を直接記述する必要がなくなり、例外安全かつコードの可読性が向上します。

サンプルプログラム

#include
include

int main() {
// 5要素のint配列を動的確保
// std::make_unique(size) を使うのが現代的な書き方です
const size_t size = 5;
std::unique_ptr arr = std::make_unique(size);

// 配列へのアクセスは通常のポインタと同様に行えます
for (size_t i = 0; i < size; ++i) { arr[i] = static_cast(i 10);
}

// 内容の確認
for (size_t i = 0; i < size; ++i) { std::cout << "arr[" << i << "] = " << arr[i] << std::endl; } // ここでスコープを抜ける際、自動的に delete[] が呼ばれます // 手動での解放処理は一切不要です return 0; }

応用・注意点: 現場で役立つ補足情報

1. std::vector との使い分け
実務では、サイズが動的に変化する配列であれば、迷わず std::vector を使用してください。std::unique_ptr は、サイズが固定であり、かつ所有権を明確に管理したい場合や、レガシーコードとのインターフェースとして使う場合に限定するのが賢明です。

2. 配列の添字アクセスに注意
std::unique_ptr は、std::vector と異なり .at() メソッドによる境界チェックがありません。生ポインタと同様、範囲外アクセスは未定義動作を引き起こすため、必ずインデックスの範囲には注意を払う必要があります。

3. 誤ったテンプレート引数の指定
std::unique_ptr arr = std::make_unique(5); のように、テンプレート引数に [] を忘れると、コンパイルエラー(または実行時の不正な解放)が発生します。静的解析ツールなどを活用し、型定義を徹底することがバグ回避の鍵となります。

コメント

タイトルとURLをコピーしました