【问题标题】:Return By Reference as an &Int通过引用返回 &Int
【发布时间】:2018-02-04 00:03:16
【问题描述】:

所以我这里有这段代码:

template <class T>
T& Array<T>::operator[](const int pos){
// Exit if pos is not valid.
if (pos < 0 || pos >= mSize) {
    return -1;
}
return mArray[pos];
}

我收到了这个错误:

error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'

我知道它正在发生,因为我在开头有引用 &T,如果它通过 if 语句无效,我将返回 -1。尽管我想拿出参考资料,但这是一个学校实验室,我无法调整原型。 所以基本上我的问题是:如果 if 语句在没有编辑任何引用的情况下通过,我如何让它以 -1 退出? 我知道我可能在某个时候已经学会了这一点,但我有有点脑子放屁,寻找最后一点没有结果。

【问题讨论】:

  • 要返回一个引用,你必须在某个地方(不是函数本地)有一个T,你可以返回一个引用。虽然不是一个很好的界面设计,因为这会阻止您在数组中存储 -1。

标签: c++ reference return


【解决方案1】:

这里的问题是界面设计。暂时让我们忽略一些技术细节,假设执行任务的函数不返回引用,而是按值返回。我们还假设它不是 operator[] 而是一个名为 GetValueAt 的函数:

template <class T>
T Array<T>::GetValueAt(const int pos)

这个签名本质上是告诉调用者“给我一个数字,我将返回数组中的相应元素”。重要的是要将此与另一种可能性区分开来,即有一个函数说“给我一个数字,如果确实对应于范围内的一个元素,我将返回那个元素”。在这种情况下,签名可能类似于

template<class T>
std::optional<T> Array<T>::GetValueAt(const int pos)

std::optional&lt;T&gt; 是一个可能确实包含 T 实例的类,或者它可能不包含任何内容。此签名识别给定整数可能不在数组范围内的事实。它接受这是一个正常的用例,并为此做好了准备。如果索引无效,则返回一个空的 std::optional。

然而,第一个签名说“无论你给我什么索引,我都会给你一个参考”。它不会将索引超出范围的情况视为正常用例,而是将其视为意外的错误情况。在这种情况下,正确的做法是抛出异常,因为没有返回的参数可以正确表达发生了什么,即:

template <class T>
T Array<T>::GetValue(const int pos)
{
if (pos < 0 || pos >= mSize) {
    throw std::invalid_argument("index out of range");
return mArray[pos];
}

请注意,在这种情况下,您很想返回 -1,但这并不能正确表示索引无效。 -1 在某些情况下可能是一个有效值,因此不适合发出错误信号。

所以总结一下,我会这样写你的方法:

template <class T>
T& Array<T>::operator[](const int pos)
{
if (pos < 0 || pos >= mSize) {
    throw std::invalid_argument("index out of range");
return mArray[pos];
}

【讨论】:

    【解决方案2】:

    你不应该返回-1。即使T 是可以从-1 构造的类型,您也不应该在错误时返回有效值。您如何区分成功的呼叫和失败的呼叫?另外,如果T 是不能从-1 构造的类型怎么办?例如。 std::string

    根据您的 iterfaces,您有几个选项可以表明该函数无法执行其职责:

    • 抛出异常(最佳选择)
    • 添加assert。这将在调试模式下结束您的程序或导致发布中出现未定义的行为。
    • 调用exit并结束程序

    为了完整起见,这里还有一些其他选项,它们是处理它的更 C-ish 方式。一般都不推荐。寻求例外。

    • 添加一个额外的参数(operator[] 不是一个选项)
    • 返回std::optional。对于示例中的引用类型(std::optional&lt;std::reference_wrapper&lt;T&gt;&gt;),进一步复杂化
    • 返回一个(可能为空)指针。不推荐。
    • 设置一个静态/全局/tread_local 变量(如errno)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 2010-12-06
      • 2014-12-11
      • 2023-03-19
      相关资源
      最近更新 更多