MyOjbect
への参照がありますが、正確なオブジェクトは条件によって異なります。だから私はこのようなことをしたい:
MyObject& ref;
if([condition])
ref = MyObject([something])
else
ref = MyObject([something else]);
コンパイラは参照を宣言することはできませんが、初期化することはできないため、今はこれを行うことができません。ここで目標を達成するために何ができますか?
初期化する必要があります。ただし、条件付きで初期化する場合は、次のようなことができます。
MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]);
私の知る限り、これは参照で行うことはできません。ポインターを使用する必要があります。
MyClass *ptr;
if (condition)
ptr = &object;
else
ptr = &other_object;
ポインターは参照と同様に機能します。メンバーアクセスに->
を使用することを忘れないでください。
これはできません。参照は何かにバインドする必要がありますが、好きではないかもしれませんが、参照があれば、nullの可能性があるポインターとは異なり、常に何かにバインドされていると想定できるため、エラーのクラス全体を防ぎます。
無効な一時オブジェクトに非const参照をバインドしようとするため、サンプルコードはとにかく機能しません。
とにかく参照する必要があるのはなぜですか?解決策の1つは、型に安価なデフォルトコンストラクターがあり、効率的に移動できるようにすることです。
MyObject obj;
if([condition])
obj = MyObject([something])
else
obj = MyObject([something else]);
それ以外の場合は、条件コードを1つ以上の関数に配置する必要があります。
const MyObject& ref = createObject([condition]);
または
const MyObject& ref = [condition] ? doSomething() : doSomethingElse();
これらのバージョンは両方ともconst参照を使用することに注意してください。これは、オブジェクトが非constである必要がある場合に一時的なものにバインドできます。参照:
MyObject obj = createObject([condition]);
これはおそらく 戻り値の最適化 のおかげで、あなたがやろうとしていたことと同じくらい効率的です。
C++では、初期化せずに参照を宣言することはできません。初期化する必要があります。
簡単な答え:そうではありません。
少し長い答え:このようなことをしてください:
MyObject& getObject()
{
if([condition])
return [something]
else
return [something else];
}
MyObject& ref = getObject();
参照に関する通常の免責事項はもちろん適用されます。
私がしたいのは、すぐに実行されるラムダです。
マップの下から変数にconst std :: string&が必要だと仮定しましょう-マップに特定のキーが含まれていない場合-スローしたいです。
int main()
{
std::map<std::string, std::string> myMap = {{"key", "value"}};
const std::string& strRef = [&]()->const std::string& {
try {
return myMap.at("key"); // map::at might throw out_of_range
}
catch (...) {
// handle it somehow and/or rethrow.
}
}(); // <- here we immediately call just created lambda.
}
std :: invoke()を使用して読みやすくすることもできます(C++ 17以降)
int main()
{
std::map<std::string, std::string> myMap = {{"key", "value"}};
const std::string& strRef = std::invoke([&]()->const std::string& {
try {
return myMap.at("key"); // map::at might throw out_of_range
}
catch (...) {
// handle it somehow and/or rethrow.
}
});
}
MyClass *ptr;
if (condition)
ptr = &object;
else
ptr = &other_object;
MyClass &ref = *ptr;
if([condition])MyObject&ref = MyObject([something]); else MyObject&ref = MyObject([something else]);