当函数没有返回值时,返回类型应该是什么?

时间:2013-06-12 09:24:15

标签: c++

在过去,你可能有这样的功能:

const char* find_response(const char* const id) const;

如果找不到该项,则可以返回null以指示该事实,否则显然会返回相关的字符串。

但是当功能改为:

const std::string& find_response(const std::string& id) const;

您返回什么表示找不到项目?

或者签名真的应该是:

bool find_response(const std::string& id, std::string& value) const;

最优雅的现代C ++方式是什么?

6 个答案:

答案 0 :(得分:22)

boost::optional。它专门针对这种情况而设计。

注意,它将作为std::optional包含在即将发布的C ++ 14标准中。更新:在审核了N3690的国家机构评论后,std::optional从C投票++ 14工作文件分成单独的技术规范。它不是n3797中C ++ 14草案的一部分。

std::unique_ptr相比,它避免了动态内存分配,并更清楚地表达了它的目的。但是,std::unique_ptr更适用于多态(例如工厂方法)和将值存储在容器中。

用法示例:

#include <string>
#include <boost/none.hpp>
#include <boost/optional.hpp>

class A
{
private:
    std::string value;
public:
    A(std::string s) : value(s) {}

    boost::optional<std::string> find_response(const std::string& id) const
    {
        if(id == value)
            return std::string("Found it!");
        else
            return boost::none;
        //or
        //return boost::make_optional(id == value, std::string("Found it!"));
    }

    //You can use boost::optional with references,
    //but I'm unfamiliar with possible applications of this.
    boost::optional<const std::string&> get_id() const
    {
        return value;
    }
};

#include <iostream>

int main()
{
    A a("42");
    boost::optional<std::string> response = a.find_response("42"); //auto is handy
    if(response)
    {
        std::cout << *response;
    }
}

答案 1 :(得分:5)

  

最优雅的现代C ++方式是什么?

一如既往,不仅仅是这个问题的一个解决方案。

如果您决定选择引用原始共振实例的任何解决方案,那么在别名和内存管理方面,尤其是在多线程环境中,您处于一个很滑的道路上。通过将响应复制到调用者,不会出现这样的问题。

今天,我会这样做:

std::unique_ptr<std::string> find_response(const std::string& id) const;

这样,你可以检查nullptr为“在过去的日子里”它是100%清楚谁有责任清理返回的实例:来电者。

我看到的唯一缺点是响应字符串的附加副本,但在测量和证明之前不要将其视为缺点。

另一种方法是在搜索std::set<>std::map<>时执行操作 - 返回std::pair<bool, const char*>,其中一个值为bool is_found,另一个值为const char* response 。这样,您就不会获得额外响应副本的“开销”,只能获得返回的std::pair<>,这可能会被编译器最大程度地优化。

答案 2 :(得分:3)

如果函数通过引用返回一个字符串,但需要能够指示不存在这样的字符串,最明显的解决方案是返回一个指针,它基本上是一个可以为null的引用,即 受到追捧的是什么。

const std::string* find_response(const std::string& id) const;

答案 3 :(得分:1)

这里有几个很好的解决方案。但为了完整起见,我想添加这个。如果您不想依赖boost::optional,您可以轻松实现自己的课程,如

class SearchResult
{
    SearchResult(std::string stringFound, bool isValid = true)
        : m_stringFound(stringFound),
        m_isResultValid(isValid)
    { }

    const std::string &getString() const { return m_stringFound; }
    bool isValid() const { return m_isResultValid; }

private:
    std::string m_stringFound;
    bool m_isResultValid;
};

显然你的方法签名就像这样

const SearchResult& find_response(const std::string& id) const;

但基本上这与增强解决方案相同。

答案 4 :(得分:0)

如果需要返回一个可以为空的实体,则可以原谅在C ++中使用指针。这被广泛接受。 但当然bool find_response(const std::string& id, std::string& value) const;非常冗长。所以这是你的选择问题。

答案 5 :(得分:-2)

我认为第二种方式更好。或者你可以这样写:

int find_response(const std::string& id, std::string& value) const;

如果此函数返回-1,则表示您没有找到响应。