97

我对 C++ 很陌生,所以我在学习时倾向于使用很多 Java 主义进行设计。无论如何,在 Java 中,如果我有一个带有“搜索”方法的类,它会TCollection< T >与特定参数匹配的对象返回一个对象,我将返回该对象,如果在集合中找不到该对象,我将返回null. 然后在我的调用函数中我会检查if(tResult != null) { ... }

在 C++ 中,我发现null如果对象不存在,我就无法返回值。我只想返回一个 T 类型的“指示符”,通知调用函数没有找到任何对象。我不想抛出异常,因为这并不是真正的异常情况。

这就是我的代码现在的样子:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

我怎样才能改变它,以便我可以给出那种标记?

4

9 回答 9

73

在 C++ 中,引用不能为空。如果你想在没有找到的情况下选择返回 null,你需要返回一个指针,而不是一个引用:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

否则,如果您坚持按引用返回,那么如果未找到该属性,则应抛出异常。

(顺便说一句,我有点担心你的方法是const并返回一个非const属性。出于哲学原因,我建议返回const Attr *。如果你也可能想修改这个属性,你可以用非const方法重载也返回一个非const属性。)

于 2010-04-14T16:44:08.820 回答
56

这里有几个可能的答案。你想返回可能存在的东西。以下是一些选项,从我最不喜欢到最喜欢:

  • 引用返回,异常信号找不到。

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

没有找到属性很可能是执行的正常部分,因此不是很例外。对此的处理会很吵。无法返回空值,因为具有空引用是未定义的行为。

  • 通过指针返回

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

很容易忘记检查 getAttribute 的结果是否为非 NULL 指针,并且很容易产生错误。

  • 使用Boost.Optional

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

boost::optional 表示这里发生了什么,并且有简单的方法来检查是否找到了这样的属性。


旁注:std::optional 最近被选入 C++17,因此这将在不久的将来成为“标准”事物。

于 2010-04-14T16:57:20.097 回答
22

您可以轻松创建一个表示 NULL 返回的静态对象。

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

在源文件的某处:

static Attr AttrNull;
于 2010-04-14T17:06:11.933 回答
3

如果你想要一个NULL返回值,你需要使用指针而不是引用。

引用本身不能是NULL.

(请注意未来的评论海报:是的,如果您真的尝试,可以将引用地址设为 NULL)。

有关引用和指针之间差异的列表,请参见我的答案

于 2010-04-14T16:44:07.823 回答
2

正如您发现的那样,您无法像在 Java(或 C#)中那样做。这是另一个建议,您可以将对象的引用作为参数传入并返回 bool 值。如果在您的集合中找到结果,您可以将其分配给正在传递的引用并返回“true”,否则返回“false”。请考虑此代码。

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string token, Operator& op)
{
    bool val = false;

    OPERATORS_MAP::iterator it = m_operators.find(token);
    if (it != m_operators.end())
    {
        op = it->second;
        val = true;
    }
    return val;
}

上面的函数必须根据键 'token' 找到 Operator,如果找到它返回 true 并将值分配给参数 Operator& op。

该例程的调用者代码如下所示

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}
于 2016-02-20T13:22:49.430 回答
1

您不能在这里返回 NULL 的原因是因为您已将返回类型声明为Attr&. 尾随&使返回值成为“引用”,它基本上是一个指向现有对象的保证不为空的指针。如果您希望能够返回 null,请更改Attr&Attr*.

于 2010-04-14T16:49:18.973 回答
0

您无法返回NULL,因为函数的返回类型是 objectreference而不是pointer.

于 2010-04-14T16:45:03.683 回答
0

在这种情况下还可以考虑另一种选择 - 取决于您的设计。您可以使用函数的参数返回值并使函数返回bool,例如

bool getAttribute(const string& attribute_name, Attr& returnAttr) const {
   //search collection
   //if found at i
        returnAttr = attributes[i];
        return true;
   //if not found
        return false;
}
于 2021-03-10T10:25:42.817 回答
-3

你可以试试这个:

return &Type();
于 2015-12-14T21:08:10.347 回答