これは基本的な質問のように聞こえますが、包括的な答えは見つかりませんでした。クラスのオブジェクトへの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
の正当な使用ですか、それともあまりにも具体的であると考えられますか?
「A」には通常の 'std :: string'だけのものがありません。それ以外の理由はありますか? 'A :: s'は左辺値を受け取ってもぶら下がり、参照は代入演算子を中断します。これはユースケースを持っているのか、純粋に学術的なのでしょうか? – nwp
'(const std :: string &&)= delete;'はあなたが望むことをするかもしれません。私はまだそれが良い考えだとは思わない。 – nwp
@nwpこれは、インスタンスのライフタイムを制御し、渡されたオブジェクトの寿命を延ばすことができないことを保証することができるユーティリティクラスで役に立ちます。私は 'std :: string'を使って高価なオブジェクトをコピーしていました。代わりの、より安全な解決法は 'shared_ptr'をこのオブジェクトに格納することです。しかし、これは簡単なシナリオでは過度のことかもしれません。 – Mikhail