c++
1/* hoge.hpp */ 2class Hoge { 3public: 4 Hoge::Hoge(); 5private: 6 std::shared_ptr<int> _value; 7};
上記のような場合、_valueはコンストラクタで初期化すべきなのでしょうか。コンストラクタでは例外を投げないような設計にすべき、と多くの場所で見てきたので、ポインタをコンストラクタで初期化すべきではないのでは、と考えました。どう対処すべきかわかりません。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
Chironianさんが言っておられますが、コンストラクタで例外を投げるべきでないというのはあまり推奨される考え方ではないです。
コンストラクタはエラーが発生してもそれを戻り値で知らせることができないためです。
コンストラクタの処理時点ですでにクリティカルなエラーに陥っている場合、コンストラクタ内で例外を投げるべきなのです。
さて、コンストラクタで特に_value
にアクセスしないとしましょう。
何らかの理由で先に空のインスタンスを作り、SetValue()
のようなセッターを用いて後から初期化できるようにしたい場合です。
次のように実際にポインタの未初期化がクリティカルになるまで例外送出を遅延する、コンストラクタでは例外を送出しないという戦略が考えられます。
cpp
1/* hoge.hpp */ 2class Hoge { 3public: 4 Hoge() = default; 5 void SetValue(std::shared_ptr<int> val) { _value = val; } 6 int DoSomething(){ 7 if (!_value) throw std::runtime_error("null!"); 8 int val = *_value; 9 // ... 10 return val; 11 } 12private: 13 std::shared_ptr<int> _value; 14};
もしくは、次のようにコンストラクタで初期化した時点から初期化を要求するという場合もあります。
個人的には、この場合を採用するのは
- コンストラクタで初期化されたリソースをコンストラクタ内で早速使いたい、もしくは
- リソースの初期化を一度きりに制限(つまりコンストラクタだけに)制限したい。
という需要からです。
cpp
1/* hoge.hpp */ 2class Hoge { 3public: 4 Hoge(std::shared_ptr<int> rsc): _value(rsc) { 5 if (!_value) throw std::runtime_error("construct error!"); 6 } 7 int DoSomething(){ 8 int val = *_value; 9 // ... 10 return val; 11 } 12private: 13 std::shared_ptr<int> _value; 14};
投稿2018/11/07 01:31
総合スコア165
0
こんにちは。
_valueはポインタのように振る舞いますが、クラス・インスタンスです。そのデフォルト・コンストラクタによる初期化でよければ、改めて初期化処理を記述する必要はありません。(コンパイラが自動的に生成しますので。)
コンストラクタでは例外を投げないような設計にすべき、と多くの場所で見てきた
かなりその記述は減ってきたと思うのですが、未だに数多くありますか。
確かにコンストラクタで投げた例外を適切に処理するのはちょっと難しいですが、コンストラクタはエラーを返却できないので例外を投げたくなることは非常に多いです。
コンストラクタから例外を投げないよう頑張るよりは、適切に例外を処理できるよう頑張る方が好ましいと思います。
スマート・ポインタを使えばそれほど難しくはないですし。
なお、デストラクタからは例外を投げない方が良いのは間違いないです。投げてはいけないというものではないですが、配列やコンテナに入れるとリークしますし、他にも問題が発生するシナリオが多数有り、それらを回避できる一般解は存在しないようです。
ですので、デストラクタから例外を投げないことは強く推奨されています。
C++11以降はデフォルトではデストラクタから例外を流出させると問答無用でプロセスが落ちます。それくらい強く推奨されています。
投稿2018/11/06 17:12
総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/07 11:10