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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2639255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:11:10  来源:igfitidea点击:

Return a "NULL" object if search result not found

c++return-valuesentinel

提问by aduric

I'm pretty new to C++ so I tend to design with a lot of Java-isms while I'm learning. Anyway, in Java, if I had class with a 'search' method that would return an object Tfrom a Collection< T >that matched a specific parameter, I would return that object and if the object was not found in the collection, I would return null. Then in my calling function I would just check if(tResult != null) { ... }

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

In C++, I'm finding out that I can't return a nullvalue if the object doesn't exist. I just want to return an 'indicator' of type T that notifies the calling function that no object has been found. I don't want to throw an exception because it's not really an exceptional circumstance.

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

This is what my code looks like right now:

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

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;
}

How can I change it so I can give that kind of marker?

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

采纳答案by Jesse Beder

In C++, references can't be null. If you want to optionally return null if nothing is found, you need to return a pointer, not a reference:

在 C++ 中,引用不能为空。如果您想在未找到任何内容的情况下选择性地返回 null,则需要返回一个指针,而不是一个引用:

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

Otherwise, if you insist on returning by reference, then you should throw an exception if the attribute isn't found.

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

(By the way, I'm a little worried about your method being constand returning a non-constattribute. For philosophical reasons, I'd suggest returning const Attr *. If you also may want to modify this attribute, you can overload with a non-constmethod returning a non-constattribute as well.)

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

回答by Kaz Dragon

There are several possible answers here. You want to return something that might exist. Here are some options, ranging from my least preferred to most preferred:

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

  • Return by reference, and signal can-not-find by exception.

    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
            throw no_such_attribute_error;
    }

It's likely that not finding attributes is a normal part of execution, and hence not very exceptional. The handling for this would be noisy. A null value cannot be returned because it's undefined behaviour to have null references.

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

  • Return by pointer

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

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

It's easy to forget to check whether a result from getAttribute would be a non-NULL pointer, and is an easy source of bugs.

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

  • Use 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

    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&>();
    }

A boost::optional signifies exactly what is going on here, and has easy methods for inspecting whether such an attribute was found.

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



Side note: std::optional was recently voted into C++17, so this will be a "standard" thing in the near future.

旁注:std::optional 最近被选入 C++17,所以这将在不久的将来成为“标准”的东西。

回答by Mark Ransom

You can easily create a static object that represents a NULL return.

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

And somewhere in a source file:

在源文件中的某处:

static Attr AttrNull;

回答by Brian R. Bondy

If you want a NULLreturn value you need to use pointers instead of references.

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

References can't themselves be NULL.

引用本身不能是NULL.

(Note to the future comment posters: Yes you can have the address of a reference be NULL if you really really try to).

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

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

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

回答by A.B.

As you have figured out that you cannot do it the way you have done in Java (or C#). Here is another suggestion, you could pass in the reference of the object as an argument and return bool value. If the result is found in your collection, you could assign it to the reference being passed and return ‘true', otherwise return ‘false'. Please consider this code.

正如您发现的那样,您不能像在 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;
}

The function above has to find the Operator against the key 'token', if it finds the one it returns true and assign the value to parameter Operator& op.

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

The caller code for this routine looks like this

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

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

回答by JSB????

The reason that you can't return NULL here is because you've declared your return type as Attr&. The trailing &makes the return value a "reference", which is basically a guaranteed-not-to-be-null pointer to an existing object. If you want to be able to return null, change Attr&to Attr*.

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

回答by codaddict

You are unable to return NULLbecause the return type of the function is an object referenceand not a pointer.

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

回答by Created

You can try this:

你可以试试这个:

return &Type();