web-dev-qa-db-ja.com

参照を宣言して、後で初期化しますか?

MyOjbectへの参照がありますが、正確なオブジェクトは条件によって異なります。だから私はこのようなことをしたい:

MyObject& ref; 
if([condition]) 
  ref = MyObject([something]) 
else 
  ref = MyObject([something else]);

コンパイラは参照を宣言することはできませんが、初期化することはできないため、今はこれを行うことができません。ここで目標を達成するために何ができますか?

51
user1861088

初期化する必要があります。ただし、条件付きで初期化する場合は、次のようなことができます。

MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]);
38
Zaffy

私の知る限り、これは参照で行うことはできません。ポインターを使用する必要があります。

MyClass *ptr;

if (condition)
    ptr = &object;
else
    ptr = &other_object;

ポインターは参照と同様に機能します。メンバーアクセスに->を使用することを忘れないでください。

15
0x499602D2

これはできません。参照は何かにバインドする必要がありますが、好きではないかもしれませんが、参照があれば、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]);

これはおそらく 戻り値の最適化 のおかげで、あなたがやろうとしていたことと同じくらい効率的です。

14
Jonathan Wakely

C++では、初期化せずに参照を宣言することはできません。初期化する必要があります。

11
user529758

簡単な答え:そうではありません。

少し長い答え:このようなことをしてください:

MyObject& getObject()
{
    if([condition]) 
        return [something] 
    else 
        return [something else];
}

MyObject& ref = getObject();

参照に関する通常の免責事項はもちろん適用されます。

9
suszterpatt

私がしたいのは、すぐに実行されるラムダです。

マップの下から変数に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.
    }
  });
}
5
Latawiec
MyClass *ptr;

if (condition)
    ptr = &object;
else
    ptr = &other_object;

MyClass &ref = *ptr;
4
Anonymous

if([condition])MyObject&ref = MyObject([something]); else MyObject&ref = MyObject([something else]);

0
VIPK