2016-03-03 14 views
12

これは基本的な質問のように聞こえますが、包括的な答えは見つかりませんでした。クラスのオブジェクトへのconst参照の格納

struct A { 
    const std::string& s; 
    A(const std::string& s) : s(s) {} 
}; 

int main() { 
    A a("abc"); 
    std::cout << a.s << std::endl; 
    return 0; 
} 

Demo:このコードスニペットを考えてみましょう。

私が理解する限り、これはUBです。文字列リテラル "abc"は、コンストラクタ内のconst std::string&にバインドされ、一時的な文字列オブジェクトを作成します。参照番号a.sにも拘束されており、一度aが構築されると破壊されます。つまり、const参照は寿命の延長を連鎖させることはできません。ダングリングリファレンス、ブーム。この特定のケースでは、私はideone.com上で何の出力も見ませんが、何かが起こる可能性があります(velociraptorsを思い出してください)。

これはわかりました。しかし、これが実際に私たちの意図であれば、オブジェクトへのconst参照を保存したいのですか?既存のものに、一時的にではなく、これは非常に自然な仕事のように聞こえますが、私はそれに1つの(ほとんど)自然な解決策しか考え出していません。 std::reference_wrapperではなく、参照することにより、コンストラクタの引数を受け入れる:std::reference_wrapper以来

A(std::reference_wrapper<const std::string> r) : s(r) {} 

が一時からコンストラクタを削除しました:

reference_wrapper(T&& x) = delete; 

これは単なる予想ように動作します。しかし、これはあまりエレガントではありません。私が考えることのできるもう1つのアプローチは、転送参照T&&を受け入れ、std::enable_ifというconst値の文字列以外のすべてを拒否することです。これはあまり優雅ではない、と私は思う。

他の方法はありますか?

UPDもう1つの質問:これはstd::reference_wrapperの正当な使用ですか、それともあまりにも具体的であると考えられますか?

+1

「A」には通常の 'std :: string'だけのものがありません。それ以外の理由はありますか? 'A :: s'は左辺値を受け取ってもぶら下がり、参照は代入演算子を中断します。これはユースケースを持っているのか、純粋に学術的なのでしょうか? – nwp

+3

'(const std :: string &&)= delete;'はあなたが望むことをするかもしれません。私はまだそれが良い考えだとは思わない。 – nwp

+0

@nwpこれは、インスタンスのライフタイムを制御し、渡されたオブジェクトの寿命を延ばすことができないことを保証することができるユーティリティクラスで役に立ちます。私は 'std :: string'を使って高価なオブジェクトをコピーしていました。代わりの、より安全な解決法は 'shared_ptr'をこのオブジェクトに格納することです。しかし、これは簡単なシナリオでは過度のことかもしれません。 – Mikhail

答えて

4

私は自然のソリューションはreference_wrapperが何を行うことであろうと言うだろう:一時から建設を防ぐ:

struct A { 
    const std::string& s; 
    A(const std::string& s) : s(s) {} 
    A(std::string&&) = delete; 
}; 

をあなたはまた、参照型のデータメンバーを有するクラスが非作ることに留意すべきです割り当て可能(移動割り当ては可能ではない)であり、割り当てオペレータを実装することは一般的に困難です。

+1

丁寧に回答してください。 1つの欠点は、このような引数が複数ある場合、不要なフレーバをすべて削除することは非常に難しいことです。 – Mikhail

+1

私はポインタのアプローチが好きではありません - それはnullptrすることはできません構文的な情報がありません。 – Mikhail

+0

@Mikhail私は不完全だが使えるオブジェクトスーパーオーダーを純粋だが使えないものと考えている;-)でも、[Core Guideline library](https://github.com/isocpp)の 'not_null ' /CppCoreGuidelines/blob/master/CppCoreGuidelines.md) – Angew

関連する問題