所以我在这里有一些代码:
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'
我知道它正在发生,因为我在开头有参考&amp; T,如果它通过if语句无效,我返回-1。尽管我想拿出参考资料,但这是一个学校实验室,我无法调整原型。 所以基本上我的问题是:如果if语句在没有编辑任何引用的情况下通过,我如何让它退出-1?我知道我可能在某些时候已经学会了这个,但我有有点大脑放屁并且寻找最后一点没有产生任何结果。
答案 0 :(得分:1)
这里的问题是界面设计。暂时让我们忽略一些技术细节,让我们假设执行任务的函数不返回引用,而是按值返回。我们假设它不是运算符[]而是一个名为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<T>
是一个可能确实包含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];
}
答案 1 :(得分:0)
您不应该返回-1
。即使T
是可以从-1
构造的类型,也不应该在错误上返回有效值。如何区分成功通话和失败通话?另外,如果T
是一种无法从-1
构建的类型,该怎么办?例如。 std::string
根据您的界面,您可以选择一些选项来表示该功能无法履行其职责:
assert
。这将以调试模式结束您的程序或在发布时导致未定义的行为。exit
并结束该计划为了完整起见,这里有一些其他选项,更多的是C-ish处理它的方式。通常没有人推荐。去寻找例外。
operator[]
的选项)std::optional
。进一步复杂的参考类型,如您的示例(std::optional<std::reference_wrapper<T>>
)errno
)。