###前提
std::unique_ptr
の使い方についてです。
std::unique_ptr
はポインタの所有権を唯一持っていて、std::move()
で所有権を移動させるということは理解しているつもりです。
今書いているのクラスのコンストラクタでstd::unique_ptr
を引数に取りたいと思い、
cpp
1class myclass{ 2 std::unique_ptr<T> ptr_; 3 4public: 5 myclass(std::unique_ptr<T> ptr) : ptr_(std::move(ptr)) {} 6 7 // ... 8};
このように書いています。(Tは任意の型と読み替えてください)このとき、使う側のコードは
cpp
1std::unique_ptr<T> p(new T()); 2myclass obj(std::move(p));
こうなると思うのですが、もしこの後もp
を使用する必要がある時はどうすればようのでしょうか?
###コード
つまり、以下のようなコードを動かしたいのですが、
cpp
1#include <iostream> 2#include <memory> 3#include <vector> 4#include <cassert> 5 6class myclass{ 7 std::unique_ptr<std::vector<int>> ptr_; 8 9public: 10 myclass(std::unique_ptr<std::vector<int>> &&ptr) : ptr_(std::move(ptr)) {} 11 12 void someProcessUsingP(){ 13 assert(ptr_);//OK, 所有権アリ 14 ptr_->push_back(10); 15 } 16}; 17 18int main(){ 19 std::unique_ptr<std::vector<int>> p(new std::vector<int>()); 20 myclass obj(std::move(p)); 21 obj.someProcessUsingP(); 22 23 /*** ここでpに所有権を取り戻したい ***/ 24 25 assert(p); //Assertion failed (所有権がない) 26 p->push_back(10); //Segmentation Fault 27 28 std::cout << p->size() << std::endl; 29 30 return 0; 31}
このままだとassert(p);
がコケて(pが所有権を持っていない), assert
をコメントアウトするとp->push_back(10);
でセグフォが起きます。
なんとかして一度std::move()
で所有権を移したstd::unique_ptr
に所有権を取り戻すことはできないのでしょうか。
###試したこと
以下のコードのように所有権を移して返すメソッドを書けば動きはするのですが、これは設計として正しいものなのか不安です。
(呼ぶつもりはありませんが)これからobj.someProcessUsingP()
が呼ばれない保証はないですし、ダメな気がします。
cpp
1#include <iostream> 2#include <memory> 3#include <vector> 4#include <cassert> 5 6class myclass{ 7 std::unique_ptr<std::vector<int>> ptr_; 8 9public: 10 myclass(std::unique_ptr<std::vector<int>> &&ptr) : ptr_(std::move(ptr)) {} 11 12 void someProcessUsingP(){ 13 assert(ptr_);//OK, 所有権アリ 14 ptr_->push_back(10); 15 } 16 17 std::unique_ptr<std::vector<int>> returnPtr(){ 18 return std::move(ptr_); 19 } 20}; 21 22int main(){ 23 std::unique_ptr<std::vector<int>> p(new std::vector<int>()); 24 myclass obj(std::move(p)); 25 obj.someProcessUsingP(); 26 27 /*** pに所有権を取り戻す ***/ 28 p = obj.returnPtr(); 29 30 assert(p);//通る(所有権がある) 31 p->push_back(10); 32 33 std::cout << p->size() << std::endl; //2 34 35 //obj.someProcessUsingP(); -> 呼ぶとAssertion failed 36 37 return 0; 38}
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/05/22 22:50