質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

4032閲覧

std::unique_ptrの所有権を取り戻したい

退会済みユーザー

退会済みユーザー

総合スコア0

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/05/22 13:50

編集2017/05/22 13:55

###前提
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}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

基本的に所有権が行ったり来たりするのはあまり良くない設計と思います。
myclassに管理を任せたのであれば、myclassにそのまま任せるのが良いです。
つまり、pへ追加する処理はできればmyclassにて実装したいものです。
要件にもよりますが、可能な時は私ならstd::vector<int>をmyclass内のprivateメンバにするだろうと思います。
手抜きですがmyclassがstd::vector<int>を継承するのもありかも知れません。

どうしても現在の構造が望ましいのでしたら、std::shared_ptr<>を使うのも手です。

個人的には1つの構造の所有権を複数のクラスが持つことには凄く抵抗を感じます。所有権が明確でないって本当にちゃんと設計できているの?って感じてしまうからですね。
でも、標準ライブラリとして勝ち残った機能ですから、恐らくそれがベストなケースはあるのだろうと思います。

投稿2017/05/22 14:23

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/05/22 22:50

所有権を行き来させるのはよくない設計なのですね。勉強になります。 myclassの方に全て実装することにします、回答ありがとうございました!
guest

0

掲示コードを見る限りは、そもそも所有権を手放すべきでないように見受けられます。

排他所有権を管理するstd::unique_ptrではなく、共有所有権を管理するstd::shared_ptrを検討してみてください。

投稿2017/05/22 14:16

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/05/22 22:57

myclassでstd::unique_ptrを別のライブラリのクラスのコンストラクタに渡さなければならず、止むを得ずstd::unique_ptrを使っている状況なので、std::shared_ptrは使えないです...すみません... でもstd::shared_ptrいいですね。次から使ってみようと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問