声明引用并稍后初始化?

时间:2013-02-14 19:59:02

标签: c++ reference

我有MyOjbect的引用,但确切的对象取决于条件。所以我想做这样的事情:

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

我现在不能这样做,因为编译器不允许我声明但不初始化引用。我能做些什么来实现我的目标?

11 个答案:

答案 0 :(得分:37)

您需要初始化它。但是如果你想有条件地初始化它,你可以这样做:

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

答案 1 :(得分:13)

你不能这样做。引用必须绑定到某些东西,你可能不喜欢它但它可以防止整个类的错误,因为如果你有一个引用,你总是可以假设它绑定到某个东西,不像一个可能为null的指针。

您的示例代码无论如何都不会起作用,因为您尝试将非const引用绑定到临时对象,这是无效的。

为什么你还需要它作为参考?一种解决方案是确保您的类型具有廉价的默认构造函数并且可以有效地移动,然后执行:

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

否则,您必须将条件代码放在一个或多个函数中:

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

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

请注意,这两个版本都使用 const 引用,如果对象必须是非const,则可以绑定到临时引用,然后再次停止尝试使用引用:

MyObject obj = createObject([condition]);

由于return value optimization

,这可能与您尝试做的一样有效。

答案 2 :(得分:13)

AFAIK这不能用参考完成。你必须使用指针:

MyClass *ptr;

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

指针的作用类似于引用。只是不要忘记使用->进行成员访问。

答案 3 :(得分:11)

在C ++中,如果没有初始化,则无法声明引用。你必须初始化它。

答案 4 :(得分:9)

简短的回答:你没有。

更长的回答:做这样的事情:

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

MyObject& ref = getObject();

关于参考文献的通常免责声明当然适用。

答案 5 :(得分:3)

MyClass *ptr;

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

MyClass &ref = *ptr;

答案 6 :(得分:3)

我喜欢做的是一个立即执行的lambda。

假设我们想要一个 const std :: string& 到地图下的变量 - 如果map不包含给定的键 - 我们想要抛出。

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

答案 7 :(得分:0)

if([条件])   MyObject&ref = MyObject([something]); 其他   MyObject&ref = MyObject([something else]);

答案 8 :(得分:0)

我通常这样做(C ++ 11或更高版本):

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

这很干净,并且允许使用具有(可能不同)构造的对象定义,这是您不能直接使用指针执行的操作,因为编译器会抱怨使用临时对象。

答案 9 :(得分:-1)

你可以使用&#34; extern&#34;关键字:第一次(假设,在头文件中),您可以使用&#34; extern&#34;声明您的声明之前的变量。关键词。稍后(在源文件中)你重复声明没有&#34; extern&#34;并为其赋值。

答案 10 :(得分:-1)

您可以使用在实际使用之前不需要初始化的模板。

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

一些旧的 IDE 可能会将其标记为错误,但它会很好地通过编译。