Declare a reference and initialize later?

C++Reference

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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]);

Solution 2 - C++

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.

Solution 3 - C++

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

Solution 4 - C++

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

Solution 5 - C++

In C++, you can't declare a reference without initialization. You must initialize it.

Solution 6 - C++

Short answer: you don't.

Marginally longer answer: do something like this:

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

MyObject& ref = getObject();

Usual disclaimers regarding references apply of course.

Solution 7 - C++

MyClass *ptr;

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

MyClass &ref = *ptr;

Solution 8 - C++

use a static dummy as place holder. or std::optional with reference_wrapper.

static X placeHolder_;
std::reference_wrapper<X> ref = placeHolder_;
   


std::optional<std::reference_wrapper<X>> ref ;    

Solution 9 - C++

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

Solution 10 - C++

I usually do this (C++ 11 or later):

std::shared_ptr<ObjType> pObj;
if(condition)
    pObj = std::make_shared<ObjType>(args_to_constructor_1);
else
	pObj = std::make_shared<ObjType>(args_to_constructor_2);

which is clean and allows using object definition with (possibly different) constructions, a thing you can't do directly with pointers as the compiler will complain from using temporary objects.

Solution 11 - C++

You can use a template which does not require initialization until you actually use it.

  template <uint8_t c>
  uint8_t& ref; 
void setup()
{
  uint8_t a=1;
  uint8_t b=2;
if(true) 
  ref<1> = a;
else 
  ref<1> = b;
}

Some old IDEs may mark it as an error but it will finely pass the compilation.

Solution 12 - C++

You can use "extern" keyword: first time (assume, in header file) you can declare your variable preceding declaration with "extern" keyword. Later (in source file) you repeat declaration without "extern" and assign value to it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1861088View Question on Stackoverflow
Solution 1 - C++ZaffyView Answer on Stackoverflow
Solution 2 - C++David GView Answer on Stackoverflow
Solution 3 - C++Jonathan WakelyView Answer on Stackoverflow
Solution 4 - C++LatawiecView Answer on Stackoverflow
Solution 5 - C++user529758View Answer on Stackoverflow
Solution 6 - C++suszterpattView Answer on Stackoverflow
Solution 7 - C++AnonymousView Answer on Stackoverflow
Solution 8 - C++alhazeemView Answer on Stackoverflow
Solution 9 - C++VIPKView Answer on Stackoverflow
Solution 10 - C++M. KhaledView Answer on Stackoverflow
Solution 11 - C++埃博拉酱View Answer on Stackoverflow
Solution 12 - C++Kirill FrolovView Answer on Stackoverflow