如果未找到搜索结果,则返回“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&
。尾随的&
使返回值成为“引用”,它基本上是一个指向现有对象的保证不为空的指针。如果您希望能够返回 null,请将 Attr&
更改为 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 - 如果在子对象中找到值,则搜索嵌套对象数组并返回父对象[重复]