如果搜索结果未找到,则返回“NULL”对象
我对C++很新颖,所以我倾向于在学习时用很多Java-ims进行设计。无论如何,在Java中,如果我有一个'搜索'方法的类将返回匹配一个特定参数的Collection< T >
对象T
,我会返回该对象,如果在该集合中找不到对象,我会返回null
。然后在我的调用函数,我只是检查if(tResult != null) { ... }
如果搜索结果未找到,则返回“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;
}
我怎样才能改变它,所以我可以给那种标记?
在C++中,引用不能为空。如果你想有选择地返回NULL如果没有找到,你需要返回一个指针,而不是一个参考:
Attr *getAttribute(const string& attribute_name) const {
//search collection
//if found at i
return &attributes[i];
//if not found
return nullptr;
}
否则,如果你坚持通过引用返回,那么你应该抛出一个异常,如果该属性ISN没有发现。
(顺便说一下,我有点担心你的方法是const
并返回一个非const
属性。对于哲学的原因,我建议恢复const Attr *
。如果你也可能要修改此属性,可以用非const
方法返回一个非const
属性以及过载。)
如果你想要一个NULL
返回值,你需要使用指针而不是引用。
参考文献本身可能不是NULL
。
(注意到未来的评论海报:是的,如果你确实尝试过,可以将参考地址设为NULL)。
See my answer here for a list of differences between references and pointers。
你无法返回NULL
,因为该函数的返回类型是一个对象reference
而不是pointer
。
你不能在这里返回NULL的原因是因为你已经声明你的返回类型为Attr&
。尾部&
使返回值成为“引用”,它基本上是一个保证不是空指针的现有对象。如果您希望能够返回空值,请将Attr&
更改为Attr*
。
这里有几种可能的答案。你想要返回可能存在的东西。这里有一些选项,从我的最不喜欢到最优选:
-
返回通过引用,信号找不到例外。
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<Attr&> getAttribute(const string& attribute_name) const { //search collection //if found at i return attributes[i]; //if not found return boost::optional<Attr&>(); }
一个boost ::可选表示到底是怎么回事就在这里,并具有检测这样的属性是否找到简单的方法。
附注:std :: optional最近被投票到C++ 17中,所以这将成为不久的将来的“标准”事情。
+1我只是提到boost ::可选第一,并且只是简单地提及其他选择。 – 2010-04-14 17:02:55
雅我看到boost ::可选在某处提到,但我认为它需要太多的开销。如果使用它是解决这些问题的最佳方法,我将开始使用它。 – aduric 2010-04-14 17:09:37
'boost :: optional'不涉及太多开销(没有动态分配),这就是为什么它非常棒。使用它与多态值需要包装引用或指针。 – 2010-04-14 18:09:43
您可以轻松创建一个表示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类型的吗? – aduric 2010-04-14 17:12:43
好点,我会修复这个例子。 – 2010-04-14 17:19:21
你可以试试这个:
return &Type();
尽管此代码片段可能会解决问题,但[包括解释](http://meta.stackexchange.com/questions/114762/explaining-entirely-基于代码的答案)确实有助于提高您的质量帖子。请记住,您将来会为读者回答问题,而这些人可能不知道您的代码建议的原因。 – NathanOliver 2015-12-14 21:10:22
这可能会返回对方法堆栈上的对象的死引用,不是吗? – mpromonet 2015-12-16 21:37:25
正好。 lllllll – Created 2015-12-17 21:32:48
当你想通了,你不能做到这一点,你在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;
}
功能上面已经找到操作员对键“令牌”,如果它发现它返回true一个并分配值参数operator &运算。
这个程序调用者的代码如下所示
Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
//Do something here if true is returned.
}
异常和NULL并不总是唯一的解决方案。你经常可以选择一个返回值来表示找不到:例如,如果没有元素匹配,'std :: find(first,last,value)'返回'last'。 – Cascabel 2010-04-14 16:47:39