【问题标题】:How to return Null as reference in C++?如何在 C++ 中返回 Null 作为参考?
【发布时间】:2019-11-19 08:25:48
【问题描述】:

我做了一些最小的代码

vector<int> items = {1, 2, 5, 0, 7};
int& getAtSafe(unsigned n) {
    if (n < items.size() && items[n] != 5) return items[n];
    else // ???
}

但是当我们找不到需要的项目时如何返回 null 呢?
P.S.原来的任务是搜索属性等于的项目。

不接受异常变体。我不需要暂停程序。
举个例子,用户输入index,每次输入错误,用户都会得到“Bad input”

【问题讨论】:

  • C++ 中没有空引用,这不是 Java。为什么你不使用std::vector::at(),这正是你想要做的?
  • 引用总是必须引用一些有效的地址。如果您尝试获得其他东西(通过肮脏的黑客),那么您将处于未定义行为的领域!
  • 例外!=“暂停程序”。向用户发出“错误输入”信号是异常的有效用例(当然调用代码必须捕获它)
  • 没有问题。也许您误解了异常的工作原理,这值得提出一个不同的问题
  • 异常可能比你想象的更有趣,你可以对你的向量进行多次访问,只需放置一个大的try-catch。错误处理你只需要一次。当然,并不总是合适的,但如果,非常方便......

标签: c++ vector return return-value


【解决方案1】:

如果函数检查索引,那么在这种情况下的一般方法是抛出异常std::out_of_range.

考虑到类模板std::vector中已经有成员函数at

如果你可能不使用异常并且任务是

附:原始任务是搜索属性等于的项目。

那么您可以使用返回迭代器的标准算法std::find_if,或者您可以编写自己的函数来返回与搜索元素对应的索引。如果没有这样的元素,则返回向量的大小,例如

#include <iostream>
#include <vector>

template <typename Predicate>
std::vector<int>::size_type find_if( const std::vector<int> &v, Predicate predicate )
{
    std::vector<int>::size_type i = 0;

    while ( i != v.size() && !predicate( v[i] ) ) ++i;

    return i;
}

int main() 
{
    std::vector<int> items = {1, 2, 5, 0, 7};

    auto i = ::find_if( items, []( const auto &item ) { return item % 2 == 0; } );

    if ( i != items.size() ) std::cout << items[i] << '\n';

    return 0;
}

【讨论】:

  • 我建议在std::vector::at上添加一个指向cppreference页面的链接到答案(en.cppreference.com/w/cpp/container/vector/at
  • @JavascriptDev 这是在发布答案后添加的...
  • @JavascriptDev 根本不接受?为什么?或者,不接受被传播出程序?然后,您可以简单地从getAtSafe(或者,更好的items.at(n))中捕获它们并打印一条错误消息。
  • @JavascriptDev 他的任务不同。实际上他需要使用标准算法std::find_if。
  • 原来我一直在做递归查找。
【解决方案2】:

C++ 具有值语义。有nullptrs 但没有空值。引用总是引用一些东西。因此,不能有对 null 的引用。

您有几个选择:

  • 抛出异常。你拒绝他们的论点是没有实际意义的。 std::vector::at 正是这样做的(但我想您的代码只是更一般情况的示例)
  • 返回一个可以是 nullptr 的指针(不推荐,因为这样你就把正确处理它的责任放在了调用者身上)
  • 返回std::optional。这再次迫使调用者处理“没有返回值”的情况,但与返回 nullptr 相比,调用者获得了一个设计良好的界面,很难用错。
  • 返回一个迭代器。在整个标准库中,end 经常用于表示“未找到元素”,因此如果您这样做,也不会感到意外。
  • 也许这不仅仅是针对不同情况的示例,那么您应该使用 std::vector::at 而不是您的手写函数并完成它。

P.S.原始任务是搜索属性等于的项目。

您应该使用std::find 在容器中查找项目。找不到元素时返回容器的end

【讨论】:

    【解决方案3】:

    在不改变原型的情况下,你只能抛出异常。

    如果可以选择更改原型,您可以:

    • 返回一个指针(并使用nullptr 作为标记)
    • 返回一个迭代器(并使用items.end() 作为标记)
    • 返回一个std::optional&lt;std::reference_wrapper&lt;int&gt;&gt;(并使用没有值作为标记,你需要C++17或boost)。

    【讨论】:

      【解决方案4】:

      C++ 中引用的一个用例是确保您没有空指针。所以根据定义,不可能返回 null 作为引用。

      但是,可以考虑不同的策略:

      • 返回迭代器:使用std::end(items)作为空值
      • 按值返回
      • 如果没有有效元素,则抛出异常

      【讨论】:

      • 按值返回并不能解决这个特殊问题。
      • 恕我直言,这不是很清楚。可以返回对空指针的引用。我承认这是对您所写内容的奇怪解释,但仍然可能会被误解
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多