topazの遊び場

いろいろやってみる

そろそろC++やるぞパート16 ポインター ~ スマートポインタ/unique_ptr ~

そろそろC++やります

そろそろC++をやります。そろそろC++をやりたいからです。
何回やるかはわかりません。基礎を理解するまではやろうと思います。

という感じでやっています。

※ 初心者がメモレベルで記録するので、技術記事としてはお力になれないかもしれません。

内容

  • 今回は、Microsoftドキュメントと他の記事を参考にして、スマートポインタの一つunique_ptrについて行います。

unique_ptr 宣言

make_unique< > ヘルパー関数を使用して、unique_ptrの宣言ができます。

unique_ptr<{型}> {変数名} = make_unique<{型}>(<{初期値}>);

int型やstring型の場合はこのように書くことができます。

unique_ptr<int> intSmtPtr = make_unique<int>(2345);
unique_ptr<int> intSmtPtr2 = make_unique<int>();
unique_ptr<string> m = make_unique<string>("Hello World!");

また、調べた限りでは、unique_ptrの宣言位は型推論auto)を用いているところが多いようです。

auto intSmtPtr = make_unique<int>(2345);
auto m = make_unique<string>("Hello World!");

型推論の詳細はまた後日行いたいと思います。

また、unique_ptrの宣言はmake_uniqueヘルパー関数を使わずに、このように書くこともできます。(参考1参考2

unique_ptr<int> intSmtPtr(new int(2345));
unique_ptr<int> intSmtPtr2(new int());
int *x = new int(2453);
unique_ptr<int> intSmtPtr3(x);

ですが、C++14 以降ではmake_uniqueを使うことが推奨されているらしいです。。(はっきり書かれている場所を見つけられませんでした。)
理由の一つとして、一つの生ポインターを二つのunique_ptrに所有権を渡すことができてしまうためです。

int *x = new int(2453);
unique_ptr<int> intSmtPtr3(x);
unique_ptr<int> intSmtPtr4(x);

この結果、intSmtPtr4(x);の宣言は実行できるのですが、スコープからintSmtPtr3intSmtPtr4が共にdeleteされることになった際に、複数回 delete することになり、実行時エラーが生じてしまいます。

自分もmake_uniqueなどのヘルパー関数を使用する方針にしようと思います。


余談 ----------

余談ですが、「make_unique;提案new_upとしたい」 という記事も見つけて面白いなと思いました。(考え方の一つですが)

簡単にいうと、new(メモリの割り当てを行う)の行為を行なっているのに、make_uniqueにはnewというキーワードが入っていないため変更したいというものでした。

こちらのブログのコードをお借りして、このコードを使用します。

//----------------------------------------
// uniq_ptrの補助
template <typename T, typename... Args>
unique_ptr<T> new_up(Args &&...args)
{
    return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template <typename T>
using up = unique_ptr<T>;
//----------------------------------------

すると、unique_ptrをこのように宣言することができました。

// 変更前
unique_ptr<int> intSmtPtr = make_unique<int>(2345);
auto intSmtPtr2 = make_unique<int>(2345);

// 変更後
up<int> intSmtPtr3 = new_up<int>(2345);

こんなことも出来るのかと勉強になりました。

余談終了----------


unique_ptrとは

宣言することは出来ましたが、「これは何?」という話です。

unique_ptrはスマートポインタの中でも、ポインターを共有できないスマートポインタです。

つまり、コピーができません。

生ポインタや他のスマートポインタではコピーができますが、unique_ptrはコピーすることができません。

int *intPtr = new int(1234);
// Ok
int *intPtr2 = intPtr;

unique_ptr<int> intSmtPtr = make_unique<int>(2345);
// コンパイルエラー
unique_ptr<int> intSmtPtr2 = intSmtPtr;

参考リスト

感想

今回は、スマートポインタの一つunique_ptrを見てみました。まだ一つ目なので、他との比較ができていませんが、「素直なポインタ」という印象です。

次回は、次のshared_ptrを触ってみたいと思います。