如何声明引用并在以后初始化

use*_*088 52 c++ reference

我对C++很新,这是我的情况.我有一个参考MyOjbect,但确切的对象取决于条件.所以我想做这样的事情:

MyObject& ref; 
if([condition]) 
  ref = MyObject([something]) 
else 
  ref = MyObject([something else]);
Run Code Online (Sandbox Code Playgroud)

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

Zaf*_*ffy 41

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

MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]);
Run Code Online (Sandbox Code Playgroud)

  • 我不能这样做,因为我实际上是在这些条件下做的事情.我在这里很困惑.对我来说这看起来很常见,为什么不允许这样做?我的编码风格是反c ++吗? (4认同)
  • @ user1861088:"我不能这样做,因为我实际上是在这些条件下做的事情"所以为什么你不实际展示你在问题中想做什么? (4认同)
  • 你可以考虑使用lambda. (3认同)

0x4*_*2D2 15

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

MyClass *ptr;

if (condition)
    ptr = &object;
else
    ptr = &other_object;
Run Code Online (Sandbox Code Playgroud)

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

  • @JosuGoñi 两者都不是真的。仅当我要分配内存时(通过“new”)。`ptr` 指向在堆栈上分配的对象。 (3认同)
  • 如果要将引用转换为引用,则可以将引用声明为"MyClass&ref =*ptr"... (2认同)

Jon*_*ely 14

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

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

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

MyObject obj; 
if([condition]) 
  obj = MyObject([something]) 
else 
  obj = MyObject([something else]);
Run Code Online (Sandbox Code Playgroud)

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

const MyObject& ref = createObject([condition]);
Run Code Online (Sandbox Code Playgroud)

要么

const MyObject& ref = [condition] ? doSomething() : doSomethingElse();
Run Code Online (Sandbox Code Playgroud)

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

MyObject obj = createObject([condition]);
Run Code Online (Sandbox Code Playgroud)

由于返回值优化,这可能与您尝试执行的操作一样高效


小智 11

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


sus*_*att 9

简短的回答:你没有.

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

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

MyObject& ref = getObject();
Run Code Online (Sandbox Code Playgroud)

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


小智 7

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

假设我们想要一个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.
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用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.
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 是的。如果只有 ppl 会回答一个问题而不是更愿意建议不应该问这个问题。这可能是实际解决 OP 的最干净的即时方法。+1。人们应该更频繁地向下滚动..大声笑 (2认同)

小智 5

MyClass *ptr;

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

MyClass &ref = *ptr;
Run Code Online (Sandbox Code Playgroud)

  • 回答时,请考虑对您编写的代码进行解释,这个答案对*非常*的老问题绝对没有任何新意。 (3认同)