首页 > 解决方案 > 使用 std::optional 和条件的安全行为

问题描述

假设我有一个std::optional<Foo>对象。我想调用其值的方法(Foo 对象),但显然只有在 Foo 存在的情况下。我可以做这样的事情:

std::optional<Foo> test;

/* stuff */

test->method(); //bad! there might not be a Foo in the optional 
              //object depending on what happened in 'stuff'
if(test) {
   if (test->method()) //always valid since 'test' condition was checked
      /* do something */
}

if (test && test->method()) //is this good coding practice? 
    /* do something */

在 SAME 条件语句中包含一个条件(测试)和一个取决于此条件(测试)为真的方法(测试->方法())是否重要?这是不好的编码礼仪吗?

标签: c++

解决方案


您正在寻找的是一个“如果非空则取消引用”运算符。C++ 没有这样的运算符。

有些语言确实有这个运算符。?.如果 C++ 采用C# 中的运算符,然后std::optional重载它,这就是代码的样子:

std::optional<foo> test = might_return_a_foo();
//If empty, short-circuit and stop. If not null, call method()
test?.method();

我认为编写显式检查没有任何问题,尽管可以使用适当的 Dereference-if-Not-Null 运算符。optional如果您确信有问题的对象将存在,您就不会从函数返回;您只需返回一个对象并避免此问题。对象可能不存在这一事实很重要,最好强制程序员为这种情况编写显式处理。

值得注意的是,您可以使事情变得更简洁:

if(auto opt = might_return_a_foo()) {//opt is deduced to be of type std::optional<foo>
    //This will only evaluate if opt contains a foo
    opt->method();
} else {
    //this will only evaluate if opt did NOT contain a foo
    std::cerr << "No Object to operate on." << std::endl;
}

此代码非常有效地处理检查,并且当且仅当对象实际存在时,对象optional在块内可见;if如果它不存在,那么您可能无论如何都不需要空optional对象。


推荐阅读