【C++】unique_ptrの使い方 スマートポインタでメモリリークを防ごう

C++で動的メモリを使う場合newdeleteを使って管理しますが、メモリリークや二重解放といった問題が発生しやすくなります。

そこで、登場するのがC++11からの機能である「スマートポインタ」

スマートポインタは、特定のスコープから外れると自動的にメモリを解放してくれるため、メモリ管理の負担が軽減されます。

今回は、ポインタの所有権を唯一持っているように振る舞うunique_ptrの使い方を紹介します。

unique_ptrの概要

unique_ptrは、特定のリソースへのポインタの所有権を唯一持っているスマートポインタです。

所有権とは、「誰がそのメモリやリソースを管理しているか」という権利を指し、unique_ptr Aが持つオブジェクトに対する所有権は、unique_ptr Aにしか割り当てられないため、そのリソースを管理できるのはunique_ptr Aのみとなります。

unique_ptrは、コピー不可なクラスとなっており、unique_ptrを他の変数に代入することはできません。

その代わり、std::moveを使って、他のunique_ptrへ所有権を譲渡することができます。

unique_ptrの使い方

unique_ptrの使い方です。

#include <iostream>
#include <memory>   // unique_ptrを使用するために必要

int main() {
  // unique_ptrを作成する
  std::unique_ptr<int> p(new int(100));

  std::cout << *p << std::endl;    // 出力値は100

  // deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}

make_uniqueを使用してunique_ptrを作成する

C++14からはmake_uniqueを使用可能。

#include <iostream>
#include <memory>   // unique_ptrを使用するために必要

int main() {
  // std::make_uniqueを使用してunique_ptrを作成する
  std::unique_ptr<int> p = std::make_unique<int>(100);

  std::cout << *p << std::endl;    // 出力値は100

  // deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}

pというunique_ptrが作られ、100を保持しています。pがスコープから抜ける(main関数から抜ける)とpが指しているメモリが自動的に解放されます。

std::moveを使用して所有権を移動する

#include <iostream>
#include <memory>   // unique_ptrを使用するために必要

int main() {
  // std::make_uniqueを使用してunique_ptrを作成する
  std::unique_ptr<int> p = std::make_unique<int>(100);

  // 所有権の譲渡
  std::unique_ptr<int> p2(std::move(p));

  std::cout << *p2 << std::endl;    // 出力値は100

  // deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}

std::moveを使用して、unique_ptr pの所有権をunique_ptr p2へ譲渡しています。これによりpは何も所有していない状態になります。

resetでリソースの解放

#include <iostream>
#include <memory>   // unique_ptrを使用するために必要

int main() {
  // std::make_uniqueを使用してunique_ptrを作成する
  std::unique_ptr<int> p = std::make_unique<int>(100);

  // リソースの解放
  p.reset();

  // リソースの再設定
  p.reset(new int(10));
  std::cout << *p << std::endl;    // 出力値は10

  // deleteでのメモリ解放不要。スコープを抜けると自動的にメモリが解放される
}

reset()でリソースの解放ができます。resetの引数に新たなリソースを指定すると、新たなリソースの所有権を設定できます。

unique_ptrまとめ

unique_ptrはC++で使われるスマートポインタの一種で、一つのオブジェクトに対する所有権を一つだけ持ちます。

unique_ptrには以下の様な特徴があります。

unique_ptrの特徴

  • 所有権が一つだけunique_ptrは一つのリソースに対して、一つの所有権しか持たない
  • コピーができないunique_ptrは他の変数に代入することはできない

もし2つのポインタが同じメモリを管理していた場合、どちらかがメモリを解放してしまうと、もう一方のポインタが使おうとしたときに既にメモリが解放されていてプログラムがクラッシュする可能性があります。

unique_ptrはこのようなバグを防ぐために、一つのリソースは一つの所有者しか持たないというルールになっています。

スポンサーリンク

  • この記事を書いた人

まさじぃ

ダメプログラマ歴17年です。 プログラミング関連の事や、 自分で使って良かったもの等の紹介をメインにやっています。

-プログラミング
-