Подтвердить что ты не робот

Как объявить ссылку и инициализировать позже

Я очень новичок в С++ и здесь моя ситуация. У меня есть ссылка на MyOjbect, но точный объект зависит от условия. Поэтому я хочу сделать что-то вроде этого:

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

Я не могу сделать это прямо сейчас, потому что компилятор не разрешает мне объявлять, но не инициализировать ссылку. Что я могу сделать для достижения своей цели здесь?

4b9b3361

Ответ 1

Вам нужно инициализировать его. Но если вы хотите условно инициализировать его, вы можете сделать что-то вроде этого:

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

Ответ 2

AFAIK это невозможно сделать со ссылкой. Вам нужно будет использовать указатель:

MyClass *ptr;

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

Указатель будет действовать аналогично ссылке. Просто не забудьте использовать -> для доступа к члену.

Ответ 3

Вы не можете этого сделать. Ссылки должны быть связаны с чем-то, вам может не понравиться, но он предотвращает целый класс ошибок, потому что, если у вас есть ссылка, вы всегда можете предположить, что она привязана к чему-то, в отличие от указателя, который может быть пустым.

Ваш примерный код не будет работать, потому что вы пытаетесь связать неконстантную ссылку на временный объект, что является недопустимым.

Зачем вам все равно быть ссылкой? Одним из решений было бы гарантировать, что ваш тип имеет недорогой конструктор по умолчанию и может быть эффективно перемещен, а затем просто выполните:

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

В противном случае вам придется поставить условный код в одну или несколько функций:

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

или

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

Обратите внимание, что обе эти версии используют ссылку const, которая может привязываться к временному, если объект должен быть неконстантным, а затем перестать пытаться использовать ссылку:

MyObject obj = createObject([condition]);

Это, вероятно, будет так же эффективно, как и то, что вы пытались сделать, благодаря оптимизации

Ответ 4

В С++ вы не можете объявить ссылку без инициализации. Вы должны инициализировать его.

Ответ 5

Короткий ответ: вы этого не делаете.

Маргинально более длинный ответ: сделайте что-то вроде этого:

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

MyObject& ref = getObject();

Разумеется, обычно применяются обьяснения относительно ссылок.

Ответ 6

MyClass *ptr;

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

MyClass &ref = *ptr;

Ответ 7

То, что я люблю делать, это лямбда, которая немедленно исполняется.

Предположим, нам нужен 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(), чтобы сделать его более читабельным (начиная с С++ 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.
    }
  });
}

Ответ 8

if ([условие]) MyObject & ref = MyObject ([что-то]); иначе MyObject & ref = MyObject ([что-то еще]);

Ответ 9

Вы можете использовать ключевое слово "extern" : первый раз (предположим, в файле заголовка) вы можете объявить свою переменную, предшествующую объявлению, ключевым словом "extern" . Позже (в исходном файле) вы повторяете объявление без "extern" и присваиваете ему значение.