「std::shared ptr」の版間の差分

提供: C++入門
移動: 案内検索
(ページの作成:「std::shared_ptr とは、C++11で追加された参照カウンタを持ち、リソースが共有できるスマートポインタです。 '''読み方'...」)
(相違点なし)

2014年1月3日 (金) 00:57時点における版

std::shared_ptr とは、C++11で追加された参照カウンタを持ち、リソースが共有できるスマートポインタです。

読み方

std::shared_ptr
えすてぃーでぃー しぇあーど ぴーてぃーあーる

概要

参照カウンタで所有者の数をカウントします。共有が増えるたびに、カウンタが1増やされ、共有が減るたびに-1されます。カウンタが0になった時点で、リソースは解放されます。 参照カウントを持つため、メモリの使用量や管理コストが上がるため、性能面では、生のポインタと比較すれば、劣ります。

基本的な使い方は、以下の通りです。

std::shared_ptr<T> name(リソースの生のポインタ);

メモリの確保の場合には、以下を通りです。

std::shared_ptr<T> name = std::make_shared<T>(コンストラクタの引数);

std::shared_ptrの作り方の例

ソースコード std_shared_ptr1.cpp

#include <iostream>
#include <memory>
using namespace std;
int main(int argc, char const* argv[])
{
        auto a = std::make_shared<int>(123);
        cout << a << endl;
        cout << *a << endl;
        *a = 456;
        cout << *a << endl;
        return 0;
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_shared_ptr1.cpp -o std_shared_ptr1

実行例

% ./std_shared_ptr1
0x2840403c
123
456

std::shared_ptrとクラスの例

ソースコード std_shared_ptr2.cpp

#include <iostream>
#include <memory>
using namespace std;
class C {
        private:
                std::string name_;
                int age_;
        public:
                C(std::string name, int age):name_(name), age_(age) {}
                virtual ~C() { cout<<__PRETTY_FUNCTION__<<endl;
                }
                void doit() {
                        cout<<__PRETTY_FUNCTION__<<endl;
                }
};
 
int main(int argc, char const* argv[])
{
        {
                auto a = std::make_shared<C>("Foo", 123);
                a->doit();
        }
        // destroy C
        return 0;
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_shared_ptr2.cpp -o std_shared_ptr2

実行例

% ./std_shared_ptr2
void C::doit()
virtual C::~C()

関数にポインタを渡す例 get()

#include <iostream>
#include <memory>
using namespace std;
 
void f(int *p) {
}
int main(int argc, char const* argv[])
{
        auto a = std::make_shared<int>(123);
        f(a.get());     // ポインタを関数に渡す例
        return 0;
}

明示的な解放の例 reset()

ソースコード std_shared_ptr4.cpp

#include <iostream>
#include <memory>
using namespace std;
 
int
main(int argc, char const* argv[])
{
        auto a = std::make_shared<int>(123);
        a.reset();// 明示的な解放
        cout << (a ? "Not reset" : "reset") << endl;    // reset と表示される
        return 0;
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_shared_ptr4.cpp -o std_shared_ptr4

実行例

% ./std_shared_ptr4
reset

解放しつつ新しいアドレスと値をセットする例

ソースコード std_shared_ptr5.cpp

#include <iostream>
#include <memory>
using namespace std;
 
int
main(int argc, char const* argv[])
{
        auto a = std::make_shared<int>(123);
        cout << a << endl;
        a.reset(new int(99));// 明示的な解放と再設定
        cout << (a ? "set" : "reset") << endl;  // set と表示される
        cout << a << endl;      // 最初とは違うアドレスが表示される
        cout << *a << endl;     // 99 が表示される
        return 0;
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_shared_ptr5.cpp -o std_shared_ptr5

実行例

% ./std_shared_ptr5
0x2840403c
set
0x28465088
99

参照カウントとオーナーの確認の例

ソースコード std_shared_ptr6.cpp

#include <iostream>
#include <memory>
using namespace std;
int
main(int argc, char const* argv[])
{
        auto a = std::make_shared<int>(123);
        cout << a.use_count() << endl;  // 参照カウントは 1
        {
                auto b = a; // b と共有する
                cout << "count is " << a.use_count() << endl;
		// 所有者がaとbなので、a は、uniqueな所有者ではないので、
		// not unique と表示される。
                cout << (a.unique() ? "a is unique" : "a is not unique") << endl;
        }
        // b が解放され、参照カウントが1減る
        cout << "count is " << a.use_count() << endl;
	// 所有者は、a しか存在しないので、 unique と表示される。
        cout << (a.unique() ? "a is unique" : "a is not unique") << endl;
 
        return 0;
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_shared_ptr6.cpp -o std_shared_ptr6

実行例

% ./std_shared_ptr6
1
count is 2
a is not unique
count is 1
a is unique

std::swapでリソースを交換する例

std::swapでリソースを交換します。

ソースコード std_shared_ptr7.cpp

#include <iostream>
#include <memory>
using namespace std;
int
main(int argc, char const* argv[])
{
        auto a = std::make_shared<int>(123);
        auto b = std::make_shared<int>(456);
 
        cout << "a is " << a << " " << *a << endl;
        cout << "b is " << b << " " << *b << endl;
 
        cout << "swap" << endl;
        std::swap(a,b);
        cout << "a is " << a << " " << *a << endl;
        cout << "b is " << b << " " << *b << endl;
 
        return 0;
}

コンパイル

g++49 -std=c++11 -I/usr/local/lib/gcc49/include/c++/ \
-Wl,-rpath=/usr/local/lib/gcc49  -pthread std_shared_ptr7.cpp -o std_shared_ptr7

実行例

% ./std_shared_ptr7
a is 0x2840403c 123
b is 0x2840404c 456
swap
a is 0x2840404c 456
b is 0x2840403c 123

関連項目