如何使用boost :: optional

pol*_*pts 27 c++ boost boost-optional

我想尝试使用boost::optional如下.

#include <iostream>
#include <string>

#include <boost/optional.hpp>

struct myClass
{
   int myInt;
   void setInt(int input) { myInt = input; }
   int  getInt(){return myInt; }
};

boost::optional<myClass> func(const std::string &str)
{
   boost::optional<myClass> value;
   if(str.length() > 5)
   {
      // If greater than 5 length string. Set value to 10
      value.get().setInt(10);
   }
   else if (str.length() < 5)
   {
      // Else set it to 0
      value.get().setInt(0);
   }
   else
   {
      // If it is 5 set the value to 5
      value.get().setInt(5);
   }

   return value;
}


int main()
{
   boost::optional<myClass> v1 = func("3124");
   boost::optional<myClass> v2 = func("helloWorld");
   boost::optional<myClass> v3 = func("hello");

   if (v1)
       std::cout << "v1 is valid" << std::endl;
   else
       std::cout << "v1 is not valid" << std::endl;

   if (v2)
       std::cout << "v2 is valid" << std::endl;
   else
      std::cout << "v3 is not valid" << std::endl;

   if (v3)
      std::cout << "v3 is valid" << std::endl;
   else
      std::cout << "v3 is not valid" << std::endl;

  return 0;
 }
Run Code Online (Sandbox Code Playgroud)

我得到以下错误

prog.exe:/usr/local/boost-1.55.0/include/boost/optional/optional.hpp:631:boost :: optional :: reference_type boost :: optional :: get()[with T = myClass; boost :: optional :: reference_type = myClass&]:断言`this-> is_initialized()'失败.

据推测,可选变量未正确初始化.怎么做正确的方法?

编辑::得到了一些非常好的答案,只是几个问题1. make_optional'func'函数结束时使用并返回它是一个好主意吗?另外2.我正在考虑分配boost::none以强调我没有分配的价值,这就是原因boost::none.但不确定这是否有效?

Rei*_*ica 26

默认构造boost::optional为空 - 它不包含值,因此您无法调用get()它.您必须使用有效值初始化它:

boost::optional<myClass> value = myClass();
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用就地工厂来避免复制初始化(但副本很可能无论如何都会被删除); 但是,我没有经验,所以我不能提供一个例子.


作为旁注,您可以使用->代替get(),如下所示:

value->setInt(10);
Run Code Online (Sandbox Code Playgroud)

但这只是风格偏好的问题,两者都同样有效.

  • @polapts要使`optional`再次为空,只需指定它:`value = boost :: none;`. (5认同)

Yak*_*ont 8

两种简单的方法:

boost::optional<myClass> func(const std::string &str)
{
  boost::optional<myClass> value;
  if(str.length() > 5) // If greater than 5 length string. Set value to 10
    value = 10;
  else if (str.length() < 5) // Else set it to 0
    value = 0;
  else // If it is 5 set the value to 5
    value = 5;

  return value;
}

boost::optional<myClass> func(const std::string &str)
{
  if(str.length() > 5) // If greater than 5 length string. Set value to 10
    return 10;
  else if (str.length() < 5) // Else set it to 0
    return 0;
  else // If it is 5 set the value to 5
    return 5;
}
Run Code Online (Sandbox Code Playgroud)

请注意,optional从永远不会返回空可选项的函数返回一个是个坏主意.

optional表现得像读取访问权限上的指针 - 如果您已经验证了可以读取的内容,则只能从中读取值.你可以检查是否有东西要读bool something_to_read = opt;.

但是,您可以随时写信给它.如果那里什么都没有,它会创造一些东西.如果那里有东西,它会覆盖它.

.get()是一种阅读,而不是一种写作,操作.(它"读取"参考)只有在使用时才能使用optional且有数据.令人困惑的是,您可以写入"读取访问" .get()返回值,因为它是非const引用.

所以也许"阅读"和"写"都是不好用的词.:)

将可选视为混合在一起的值和指针有时是有帮助的.有一个可能为空的指针指向拥有的内存缓冲区,该缓冲区可能或可能不包含该类型的副本.

如果optional中的指针为null,则缓冲区未初始化.如果它指向缓冲区,则初始化缓冲区.

.get()取消引用指针并返回结果引用而不进行检查. =检查指针,如果它为null,它从rhs到缓冲区执行复制构造并设置指针.如果没有,它只是分配给缓冲区.

(指针是概念性的:通常作为bool标志实现).

我发现使用*optional比使用optional.get()取消引用运算符更明显的"你必须在取消引用之前检查"更好.

  • @KonradRudolph等等,什么,你认真吗?当我看到那段代码时,我可能会诅咒. (7认同)

utn*_*tim 8

怎么做正确的方法?

boost::optional<myClass> func(const std::string &str)
{
    if(str.length() > 5)
        return myClass{10};
    if(str.length() < 5)
        return myClass{0};
    return myClass{5};
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,这段代码不需要boost :: optional,因为没有返回空对象的代码分支(它在语义上等同于返回myClass实例).

要返回空的可选项,请使用以下命令:

boost::optional<myClass> func(const std::string &str)
{
    if(str.length() > 5)
        return myClass{10};
    if(str.length() < 5)
        return myClass{0};
    return boost::none; // return empty object
}
Run Code Online (Sandbox Code Playgroud)

惯用客户端代码(不要预先初始化您的值):

int main()
{
    if (auto v1 = func("3214"))
        // use *v1 to access value
        std::cout << "v1 is valid" << std::endl;
    else
        std::cout << "v1 is not valid" << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 对于空的可选,你可以只返回boost:none;` (4认同)