如何返回不可用的const引用

sjd*_*ing 17 c++ c++11

说我有以下功能:

const std::string& Cat::getKittenName() const
{
  Kitten* kitty = getKitty();
  return kitty->getName();
}
Run Code Online (Sandbox Code Playgroud)

哪里Kitten::getName返回一个const std::string&如何最好地处理的情况kittynullptr哪个?我可以返回,std::string("")但后来我返回一个临时和实际保证未定义行为的引用.我可以更改getKittenName函数返回一个std::string来解决这个问题,但后来我为所有kitty可用的情况引入了一个冗余副本.现在我觉得最好的选择是:

const std::string& Cat::getKittenName() const
{
  Kitten* kitty = getKitty();
  if (kitty)
  {
    return kitty->getName();
  }
  static std::string empty("");
  return empty;
}
Run Code Online (Sandbox Code Playgroud)

唯一的问题可能是"魔法静力学"不可用.这个解决方案有什么问题,或者有更好的方法吗?

Rei*_*ica 25

你有几个选择,真的.

  • 最简单的就是返回std::string,但是你提到你出于性能原因不希望这样做.我会说你应首先进行分析,以确保它会出现明显的性能问题,因为所有其他解决方案都会使代码更复杂,因此至少有一点难以维护.但是,让我们说它看起来确实很重要.

  • 如果您担心未实现线程安全的函数范围静态,则可以将回退值创建为以下静态成员Cat:

    class Cat {
      static const std::string missingKittenName;
    
    public:
      const std::string& Cat::getKittenName() const
      {
        Kitten* kitty = getKitty();
        if (kitty)
          return kitty->getName();
        else
          return missingKittenName;
      }
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 由于Kitten::getName()显然返回引用(否则你不会担心副本),你也可以返回一个指针:

    const std::string* Cat::getKittenName() const
    {
      Kitten* kitty = getKitty();
      if (kitty)
        return &kitty->getName();
      else
        return nullptr;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 您可以返回对字符串的可选引用:

    boost::optional<const std::string&> Cat::getKittenName() const
    {
      Kitten* kitty = getKitty();
      if (kitty)
        return kitty->getName();
      else
        return boost::none;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    由于C++ 17 optional是标准库的一部分std::optional,因此不再需要依赖Boost.

  • 如果缺少名称这一事实是异常情况(错误),您可以抛出异常:

    const std::string& Cat::getKittenName() const
    {
      Kitten* kitty = getKitty();
      if (kitty)
        return kitty->getName();
      else
        throw std::invalid_argument("Missing kitten");
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 也许这是C程序员仍然留在我身上,但我非常喜欢在这种情况下返回一个const指针(我也是可选的粉丝,不要误解我的意思......)但是*可选的const引用的想法*只是不适合我... (2认同)
  • 在 C++17 中将引用放入 std::Optional 中是非法的。 (2认同)

Ric*_*ges 6

返回对const static std :: string的引用.

原因:

  • "魔法静力学"并不神奇,它们是c ++标准的一部分.
  • 静态是在代码第一次流过它们时构建的(即曾经一次)
  • 从c ++ 11开始,静态构造是线程安全的.
  • 静态对象在程序结束时以正确的顺序正确释放
  • 一个冗余静态对象的性能损失完全可以忽略不计,并且比测试null的返回指针的成本要低得多.

如果你在pre-c ++ 11编译器上有多线程,那么你需要编写一个线程安全的单例来制作默认字符串,或者在文件范围内定义它.

C++ 11:

const std::string& Cat::getKittenName() const
{
  static const std::string noname { /* empty string */ };
  Kitten* kitty = getKitty();
  if (kitty)
  {
    return kitty->getName();
  }
  return noname;
}
Run Code Online (Sandbox Code Playgroud)

C++ 03:

namespace {
    const std::string noname;
}

const std::string& Cat::getKittenName() const
{
  Kitten* kitty = getKitty();
  if (kitty)
  {
    return kitty->getName();
  }
  return noname;
}
Run Code Online (Sandbox Code Playgroud)