Last active
June 15, 2020 04:44
-
-
Save hmito/32d8ad0c7f216db73239 to your computer and use it in GitHub Desktop.
C++11スマートポインタ入門 ref: https://qiita.com/hmito/items/db3b14917120b285112f
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//通常のポインタがほしい時には、get関数を使う。 | |
//ポインタの所有権はunique_ptrが保持し続ける | |
int* pint; | |
pint = ptr.get(); | |
//所有権自体を放棄する場合は、release関数を使う | |
//この場合、メモリの解放自体は自分で行う必要がある | |
pint = ptr.release(); | |
delete pint; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
//型名[]をテンプレート引数に指定することで、配列も扱える | |
std::unique_ptr<int[]> ptrArray(new int[10]); | |
//配列型の場合operator[](size_t)を使うことができる | |
for(int i=0;i<10;++i){ | |
ptrArray[i]=i; | |
} | |
}//配列型の場合、自動的にdelete[]が呼ばれて解放される。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//コンストラクタや、reset関数を使ってのメモリ割り当てが可能 | |
std::shared_ptr<int> ptr(new int(10)); | |
std::shared_ptr<int> ptr2; | |
ptr2.reset(new int(10)); | |
//make_shared関数を使うと、効率よくメモリを確保できる(C++11から使える) | |
std::shared_ptr<int> ptr3=std::make_shared<int>(10); | |
//複数の引数を持つコンストラクタも、make_sharedから呼び出せる | |
typedef std::pair<int,double> int_double_t; | |
std::shared_ptr<int_double_t> ptr4=std::make_shared<int_double_t>(10,0.4); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//コピーコンストラクタや、コピー代入演算子もOK | |
//所有権は、ptr、ptr2、ptr3の三者が保持する | |
std::shared_ptr<int> ptr=std::make_shared<int>(10); | |
std::shared_ptr<int> ptr2(ptr); //ok ptrとptr2で所有権を共有 | |
std::shared_ptr<int> ptr3; | |
ptr3=ptr; //ok ptrとptr3で所有権を共有 | |
//ムーブコンストラクタや、ムーブ代入演算子はOK | |
//この時、所有権は移動する | |
std::shared_ptr<int> ptr4(std::move(ptr)); //ok ptrの所有権がptr4に移動する | |
std::shared_ptr<int> ptr5; | |
ptr5=std::move(ptr2); //ok ptr2の所有権がptr5に移動する |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//コンストラクタでunique_ptrからムーブ | |
//所有権がuptrからptrに移動する | |
std::unique_ptr<int> uptr(new int(10)); | |
std::shared_ptr<int> ptr(std::move(uptr)); | |
//代入演算子で、ムーブ | |
//こちらも同様に、所有権がuptr2からptr2に移動する | |
std::unique_ptr<int> uptr2(new int(10)); | |
std::shared_ptr<int> ptr2; | |
ptr2=std::move(uptr2); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> ptr=std::make_shared<int>(10); | |
{ | |
//ptrから所有権をコピー | |
std::shared_ptr<int> ptr2(ptr); | |
}//ここでptrのディストラクタが呼ばれ、ptr2は所有権を放棄 | |
//ptrがまだ所有権を保有しているので、メモリは解放されていない | |
//引数なしやnullptrを引数としてreset関数を呼んでも、明示的に所有権を放棄できる | |
//ptrが所有権を放棄すると、所有権を持つポインタがなくなるので、ここでメモリ解放 | |
ptr.reset(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> ptr; | |
//メモリの所有権を保持しているかどうかは、boolの文脈で使用することで判定できる | |
//所有していれば、trueを返す | |
if(ptr){ | |
//---所有しているときの処理--- | |
} | |
//bool変数への代入も可能 | |
bool CanAccess=ptr; | |
//所有者の数を確認するには、use_count関数を使う | |
std::cout<<"use_count="<<ptr.use_count()<<std::endl; | |
//所有者が唯一であることを確認するには、unique関数を使う | |
//use_count()==1ならtrue, それ以外ならfalseとなる | |
if(ptr.unique()){ | |
std::cout<<"unique"<<std::endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<std::string> pStr=std::make_shared<std::string>("test"); | |
//operator*()でstring型呼び出し | |
// "test" と表示される | |
std::cout<<*pStr<<std::endl; | |
//operator->()で、string型のsize関数を呼び出せる | |
unsigned int StrSize=pStr->size(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> ptr=std::make_shared<int>(10); | |
//通常のポインタがほしい時には、get関数を使う。 | |
//ポインタの所有権はshared_ptrが保持し続ける | |
int* pint; | |
pint=ptr.get(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
//[]型名をテンプレート引数に指定することで、配列も扱える | |
//第2引数で、配列用にdeleterを指定 | |
//deleterを明示的に指定する際には、make_sharedは使えない | |
std::shared_ptr<int> ptrArray(new int[10], std::default_delete<int[]>()); | |
//operator[]は使えない | |
//代わりに、get関数からアクセスはできる | |
for(int i=0;i<10;++i){ | |
//ptrArray[i]=i; //===ERROR=== | |
ptrArray.get()[i]=i; //ok | |
} | |
}//default_delete<int[]>を指定しておけば、自動的にdelete[]が呼ばれて解放される。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//コンストラクタや代入演算子で、shared_ptrを受け取る | |
std::shared_ptr<T> sptr=std::make_shared<int>(10); | |
std::weak_ptr<T> wptr(sptr); | |
std::weak_ptr<T> wptr2; | |
wptr2=sptr; | |
//ポインタを直接受け取ることはできない | |
//std::weak_ptr<T> wptr3(new int(10)); //===ERROR=== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> sptr=std::make_shared<int>(10); | |
std::weak_ptr<int> wptr(sptr); | |
//コピーコンストラクタや、コピー代入演算子もOK | |
std::weak_ptr<int> wptr2(wptr); | |
std::weak_ptr<int> wptr3; | |
wptr3=wptr; | |
//ムーブコンストラクタや、ムーブ代入演算子もOK | |
//この時、wptr2,wptr3は参照を失う | |
std::weak_ptr<int> wptr4(std::move(wptr2)); | |
std::weak_ptr<int> wptr5; | |
wptr5=std::move(wptr3); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> sptr=std::make_shared<int>(10); | |
{ | |
std::weak_ptr<int> wptr(sptr); | |
}//ディストラクタで参照を解放 | |
std::weak_ptr<int> wptr2(sptr); | |
//reset関数で明示的に解放 | |
wptr2.reset(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> sptr=std::make_shared<int>(10); | |
std::weak_ptr<int> wptr(sptr); | |
//参照先のメモリが解放されていないかどうかはexpired関数を使う | |
if(wptr.expired()){ | |
std::cout<<"expired"<<std::endl; | |
} | |
//所有者の数を確認するには、use_count関数を使う | |
std::cout<<"use_count="<<wptr.use_count()<<std::endl; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::shared_ptr<int> sptr=std::make_shared<int>(10); | |
std::weak_ptr<int> wptr(sptr); | |
{ | |
//lock関数によって、参照先を保持するshared_ptrを取得する | |
std::shared_ptr<int> ptr=wptr.lock(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//コンストラクタの引数として、動的確保したメモリのアドレスを指定 | |
std::unique_ptr<int> ptr(new int(10)); | |
//reset関数を使って、後から代入することもできる | |
std::unique_ptr<int> ptr2; | |
ptr2.reset(new int(10)); | |
//C++14以降であれば、make_unique関数を使うこともできる | |
std::unique_ptr<int> ptr3=std::make_unique<int>(10); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::unique_ptr<int> ptr(new int(10)); | |
//コピーコンストラクタや、コピー代入演算子はエラー | |
//std::unique_ptr<int> ptr2(ptr); //===ERROR=== | |
std::unique_ptr<int> ptr3; | |
//ptr3=ptr; //===ERROR=== | |
//ムーブコンストラクタや、ムーブ代入演算子はOK | |
//この時、所有権が移動する | |
std::unique_ptr<int> ptr4(std::move(ptr)); //ok ptrの所有権がptr4に移動する | |
std::unique_ptr<int> ptr5; | |
ptr5=std::move(ptr4); //ok ptr4の所有権がptr5に移動する |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
std::unique_ptr<int> ptr(new int(10)); | |
}//ここでptrのディストラクタが呼ばれ、自動的に解放される | |
//引数なしやnullptrを引数としてreset関数を呼んでも、明示的に解放できる | |
std::unique_ptr<int> ptr2(new int(10)); | |
ptr2.reset(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::unique_ptr<int> ptr; | |
//メモリの所有権を保持しているかどうかは、boolの文脈で使用することで判定できる | |
//所有していれば、trueを返す | |
if(ptr){ | |
//---所有しているときの処理--- | |
} | |
//bool変数への代入でも、所有権の有無を取得可能 | |
bool CanAccess=ptr; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::unique_ptr<std::string> pStr(new std::string("test")); | |
//operator*()でstring型を参照 | |
// "test" と表示される | |
std::cout<<*pStr<<std::endl; | |
//operator->()で、string型のsize関数を呼び出せる | |
unsigned int StrSize = pStr->size(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//int型のリソースをstorageから確保する | |
int* malloc_int_from_storage(); | |
//int型のリソースをstorageから解放する | |
void free_int_from_storage(int* ptr); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<memory> | |
int main(){ | |
//int型のメモリを動的に確保し、その所有権をauto_ptrに委ねる | |
std::auto_ptr<int> ptr(new int(10)); | |
//operator*()で生ポインタのようにアクセスできる | |
for(int i=0;i<10;++i){ | |
*ptr+=i; | |
} | |
std::cout<<"ptr="<<*ptr<<std::endl; | |
return 0; | |
}//ディストラクタ内で、自動的にptrの中身をdelete |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<memory> | |
class hoge{ | |
private: | |
std::auto_ptr<int> ptr; | |
public: | |
hoge(int val_):ptr(new int(val_)){} | |
int getValue()const{return *ptr;} | |
}; | |
int main(){ | |
//hogeのコンストラクタでint型を動的に確保しauto_ptrに委ねる | |
hoge Hoge(10); | |
//コピーコンストラクタで二つ目のhogeを作成 | |
//この時Hoge.ptrからHoge.ptr2に所有権が移動! | |
hoge Hoge2(Hoge); | |
//Hogeの値を呼び出す | |
Hoge.getValue(); //===ERROR=== | |
//実行時エラー! | |
//Hoge.ptrはすでに所有権を失っているので、アクセスできない | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<memory> | |
class hoge{ | |
public: | |
std::shared_ptr<hoge> ptr; | |
}; | |
int main(){ | |
std::shared_ptr<hoge> pHoge1=std::make_shared<hoge>(); | |
std::shared_ptr<hoge> pHoge2=std::make_shared<hoge>(); | |
//Hoge1のメンバ変数で、pHoge2を参照する | |
pHoge1->ptr=pHoge2; | |
//Hoge2のメンバ変数で、pHoge1を参照する | |
pHpge2->ptr=pHoge1; | |
return 0; | |
}//shared_ptrのディストラクタが呼ばれるのに、確保した二つのhogeが解放されない。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<memory> | |
#include"memory_from_storage.hpp" | |
//free_int_from_storageを使ってメモリを解放する関数オブジェクトを定義する。 | |
struct deleter_for_storage{ | |
void operator()(int* ptr_){ | |
free_int_from_sotrage(ptr_); | |
} | |
}; | |
int main(){ | |
//テンプレート第二引数で、deleterを指定する | |
std::unique_ptr<int, deleter_for_storage> ptr(malloc_int_from_storage()); | |
//deleteではなく、free_int_from_storageがメモリ解放の際に呼ばれる。 | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
int main(){ | |
int* ptr=new int(10); | |
for(int i=0;i<10;++i){ | |
*ptr+=i; | |
} | |
std::cout<<"ptr="<<*ptr<<std::endl; | |
delete ptr; //これを忘れると、メモリリーク | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<memory> | |
class hoge{ | |
private: | |
int* ptr; | |
public: | |
hoge(int val_){ | |
if(val_>0)ptr=new int(val_); | |
} | |
~hoge(){delete ptr;} | |
}; | |
int main(){ | |
//hogeのコンストラクタでnewが呼ばれない | |
hoge Hoge(-1); | |
return 0; | |
}//=== ERROR=== ディストラクタでdeleteが呼ばれるので、動作は未定義! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<memory> | |
class hoge{ | |
private: | |
std::unique_ptr<int> ptr; | |
public: | |
hoge(int val_):ptr(new int(val_)){} | |
int getValue()const{return *ptr;} | |
}; | |
int main(){ | |
//hogeのコンストラクタでint型を動的に確保しunique_ptrに委ねる | |
hoge Hoge(10); | |
//unique_ptrはコピーできないので、 | |
//コピーコンストラクタで作成しようとすると、コンパイルエラー | |
//hoge Hoge2(Hoge); //===ERROR=== | |
//明示的にmoveするならOK | |
hoge Hoge2(std::move(Hoge)); | |
return 0; | |
}//auto_ptr同様、ディストラクタで自動的にメモリ解放 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<memory> | |
class hoge{ | |
public: | |
//shared_ptrで所有権を得る代わりに、weak_ptrで参照する | |
std::weak_ptr<hoge> ptr; | |
}; | |
int main(){ | |
std::shared_ptr<hoge> pHoge1=std::make_shared<hoge>(); | |
std::shared_ptr<hoge> pHoge2=std::make_shared<hoge>(); | |
//Hoge1のweak_ptrで、pHoge2を参照する | |
pHoge1->ptr=pHoge2; | |
//Hoge2のweak_ptrで、pHoge1を参照する | |
pHpge2->ptr=pHoge1; | |
}//所有権は、pHoge1, pHoge2しかそれぞれ持っていないので、正しく解放される |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment