【プログラミング言語Ⅳ】講義メモ

講義メモ
・「6.メモリの管理:6.5 スマートポインタ:リソースの所有権」の続きから
 https://rinatz.github.io/cpp-book/ch06-05-smart-pointers/

6.メモリの管理:6.5 スマートポインタ:リソースの所有権【再掲載】

・ポインタはコピー可能なため、ポインタが指す先のリソースを複数のオブジェクトから参照することが可能
・動的確保したリソースを扱う場合、 誤って delete を忘れたり、同じリソースを複数回 delete したりすることを防ぐために、 
 どの変数がリソースの所有権(リソースを参照する権利と解放する権利)を持つのかをプログラマが細心の注意を払ってコードを
 書く必要がある

提出フォロー:演習:リソースの所有権 project1/p0604501.cpp

・リソースの所有権のサンプルソースを動作可能にしよう
・「a と b のどちらを delete するべきか?」の下で両方をdeleteして、どうなるか確認しよう
⇒ どちらをdeleteしても良いが、両方を消そうとすると、delete済なので異常終了する

作成例

//演習:リソースの所有権 project1/p060501.cpp
#include <iostream>
int main() {
    int* a = new int(100); //動的に領域を確保
    int* b = a; // b からも a と同じリソースを参照できるようにする。
    // a と b のどちらを delete するべきか?
    delete a;
    std::cout << "delete a is done" << std::endl;
    delete b; //対象が存在しないので異常終了する
    std::cout << "delete b is done" << std::endl;
    return 0;
}

6.メモリの管理:6.5 スマートポインタ:std::shared_ptr

・動的確保したリソースの所有権を共有することができるスマートポインタ
・スマートポインタは  ヘッダにて提供されている
・内部で所有権を持つオブジェクトの一覧を管理し、所有者がいなくなった時に自動的に delete する仕組みを提供する
・std::shared_ptr オブジェクトを生成するには、 std::make_shared を利用する
・デストラクタはオブジェクトの生存期間が尽きる(消える)とシステムが判断したときに自動的に呼び出す関数
・デストラクタはクラスの中で記述するものだが(副テキストp.471)、スマートポインタの利用により、
 動的に確保された領域に対しても delete が動作するようになっている

演習:std::shared_ptr project1/p060502.cpp

・std::shared_ptrのサンプルソースを試してみよう
・xとyの明示的な消去(delete)ができるかどうか確認しよう

作成例

//演習:std::shared_ptr project1/p060502.cpp
#include <iostream>
#include <memory>
int main() {
    std::shared_ptr<int> x = std::make_shared<int>(100); // int* x = new int(100); の代わり
    // 所有者は1人。
    { //ブロックにすることでyの有効範囲(生存期間)を制限している
        std::shared_ptr<int> y = x; // 通常のポインタ同様、コピーすることで所有権が共有される
        // 所有者が2人に増える。
        std::cout << "*y = " << *y << std::endl;
        // delete y; //シェアードポインタのdeleteは不可
    } // y が破棄されて所有者が1人になる。(yの有効範囲(生存期間)はここまでなので)
    std::cout << "*x = " << *x << std::endl;
    // delete x; //シェアードポインタのdeleteは不可
    return 0;
} // 所有者が0人になるので、 x のデストラクタで自動的に delete が行われる。

6.メモリの管理:6.5 スマートポインタ:std::unique_ptr

・std::shared_ptr と違い、コピーが出来ないのが std::unique_ptr。
・よって、そのため、確保したリソースの所有者が常に1人になるようにしたい場合に用いる。

演習:std::unique_ptr project1/p060503.cpp

・std::unique_ptrのサンプルソースを試してみよう
・「// std::unique_ptr y = x;」のコメントアウトを戻して、どういうエラーになるか確認しよう
 ⇒ コンパイルエラーになるが、VC++では「C++関数は参照できません -- これは削除された関数です」というエラーが表示され、
 誤解を招くので注意。

作成例

//演習:std::unique_ptr project1/p060503.cpp
#include <iostream>
#include <memory>
int main() {
    std::unique_ptr<int> x(new int(100)); //コピーできないスマートポインタで生成される
    std::unique_ptr<int> y = x; // コピー出来ないのでコンパイルエラーになる
    std::cout << *x << std::endl;
    return 0;
} // x が所有しているリソースが解放される。

6.メモリの管理:6.5 スマートポインタ:std::unique_ptr(続き)

・所有権の共有はできないが、std::move を使うことで所有権の移動は出来る
・このことで std::shared_ptr よりも軽快に動作する

演習:std::unique_ptr その2 project1/p060504.cpp

・std::unique_ptrの2つめのサンプルソースを試してみよう
・「所有権を移動したため、x は何も所有していない」ことを確認する処理を追記しよう

作成例

//演習:std::unique_ptr その2 project1/p060504.cpp
#include <iostream>
#include <memory>
int main() {
    std::unique_ptr<int> x(new int(100));
    std::unique_ptr<int> y(std::move(x)); // ムーブは出来るため、所有権の移動は可能。
    std::cout << "*y = " << *y << std::endl;
    // 所有権を移動したため、x は何も所有していない。
    std::cout << "*x = " << *x << std::endl; //よってここで異常終了する(コンパイルエラーにはならない)
    return 0;
} // y が所有しているリソースが解放される。

※ std::auto_ptr、std::weak_ptrは割愛

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です