如果未找到搜索结果,则返回“NULL”对象

时间:2010-04-14 16:41:46

标签: c++ return-value sentinel

我对C ++很陌生,所以在我学习的时候,我倾向于设计很多Java主义。无论如何,在Java中,如果我的类具有“搜索”方法,该方法将从匹配特定参数的T返回对象Collection< 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;
}

如何更改它以便我可以提供这种标记?

9 个答案:

答案 0 :(得分:61)

在C ++中,引用不能为null。如果要在没有找到任何内容的情况下选择返回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属性。)

答案 1 :(得分:52)

这里有几个可能的答案。您想要返回可能存在的内容。以下是一些选项,从我最喜欢的到最喜欢的:

  • 以引用方式返回,并且异常无法找到信号。

    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,所以这将是不久的将来的“标准”事情。

答案 2 :(得分: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;

答案 3 :(得分:3)

如果您想要NULL返回值,则需要使用指针而不是引用。

参考文献本身不能是NULL

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

See my answer here for a list of differences between references and pointers

答案 4 :(得分: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&amp;同前。

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

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}

答案 5 :(得分:1)

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

答案 6 :(得分:0)

您无法返回NULL,因为该函数的返回类型是对象reference而不是pointer

答案 7 :(得分: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;
}

答案 8 :(得分:-4)

你可以试试这个:

return &Type();