Declare a reference and initialize later?

I have a reference to some class MyObject, but the exact object depends on a condition. I want to do something like this:

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

I cannot do this right now because the compiler does not allow me to declare but not initialize a reference. What can I do to achieve my goal here?


You need to initliaze it. But if you would like to conditionally initialize it, you can do something like this:

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

AFAIK this can't be done with a reference. You'd have to use a pointer:

MyClass *ptr;

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

The pointer will act similar to a reference. Just don't forget to use -> for member access.


You can't do this. References must be bound to something, you may not like it but it prevents a whole class of errors, because if you have a reference you can always assume it's bound to something, unlike a pointer which could be null.

Your example code wouldn't work anyway because you attempt to bind a non-const reference to a temporary object, which is invalid.

Why do you need it to be a reference anyway? One solution would be to ensure your type has an inexpensive default constructor and can be efficiently moved, then just do:

MyObject obj; 
if([condition]) 
  obj = MyObject([something]) 
else 
  obj = MyObject([something else]);

Otherwise you'd have to put the conditional code in one or more functions, either:

const MyObject& ref = createObject([condition]);

or

const MyObject& ref = [condition] ? doSomething() : doSomethingElse();

Note that both these versions use a const reference, which can bind to a temporary, if the object must be non-const, then again stop trying to use a reference:

MyObject obj = createObject([condition]);

This will probably be just as efficient as what you were trying to do, thanks to the return value optimization


What I like to do is a lambda that's immediately executed.

Let's suppose we want a const std::string& to a variable from under the map - if map does not contain given key - we want to throw.

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.
}

You could also use std::invoke() to make it more readable (since 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.
    }
  });
}