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

Posted

技术标签:

【中文标题】如果未找到搜索结果,则返回“NULL”对象【英文标题】:Return a "NULL" object if search result not found 【发布时间】:2011-02-08 00:23:28 【问题描述】:

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

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

【问题讨论】:

Exception 和 NULL 并不总是唯一的解决方案。您通常可以选择一个值来返回指示未找到:例如,std::find(first, last, value) 如果没有元素匹配,则返回 last 【参考方案1】:

在 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 属性。)

【讨论】:

谢谢。顺便说一句,这是设计这种例程的公认方式吗? @aduric:是的。引用意味着结果必须存在。指针暗示结果可能不存在。 只是好奇,我们现在应该为 c++11 返回nullptr 而不是NULL 吗? 是的,在 C++11 及更高版本中,始终使用 nullptr 而不是 NULL。如果您需要向后兼容早期版本,则不要【参考方案2】:

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

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

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,因此这将在不久的将来成为“标准”。

【讨论】:

+1 我只想先提一下 boost::optional,然后简要提一下其他替代方案。 是的,我在某处看到了 boost::optional ,但我认为它需要太多开销。如果使用它是解决这类问题的最佳方法,我将开始使用它。 boost::optional 不涉及太多开销(没有动态分配),这就是它如此出色的原因。将它与多态值一起使用需要包装引用或指针。 @MatthieuM。很可能 aduric 所指的开销不是性能,而是在项目中包含外部库的成本。 我的回答的一个附录:请注意,有一项运动正在进行中,将 optional 标准化为 std 组件,可能是 C++17。因此,这项技术值得了解。【参考方案3】:

您可以轻松创建一个表示 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;

【讨论】:

NodeNull 不应该是 Attr 类型吗?【参考方案4】:

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

引用本身不能是NULL

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

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

【讨论】:

【参考方案5】:

正如您发现的那样,您无法像在 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'找到运算符,如果找到它返回true并将值分配给参数Operator&op。

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

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))

    //Do something here if true is returned.

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

在这种情况下还可以考虑另一种选择 - 取决于您的设计。您可以使用函数的参数返回值并使函数返回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;

【讨论】:

【参考方案9】:

你可以试试这个:

return &Type();

【讨论】:

虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。 这可能会返回对方法堆栈上对象的死引用,不是吗?

以上是关于如果未找到搜索结果,则返回“NULL”对象的主要内容,如果未能解决你的问题,请参考以下文章

FirstOrDefaultAsync()SingleOrDefaultAsync()方法的区别

FirstOrDefaultAsync()SingleOrDefaultAsync()方法的区别

javascript - 如果在子对象中找到值,则搜索嵌套对象数组并返回父对象[重复]

当未找到结果时,其中 First() 似乎返回 null 的 Linq 查询

使用 in_array 搜索 (null, false)

如果结果返回 null 则返回所有内容