如果您违反对模板类型的任何要求,提供错误的函数参数或任何其他违反合同的行为,标准库通常会允许未定义的行为。在用户库中允许这样做是否被认为是一种好习惯?什么时候这样做是否公平?
考虑为容器编写operator[]
:
template <typename t>
T& container<T>::operator[](int i)
{
return internal_array[i];
}
如果i
索引超出internal_array
的范围,我们会遇到未定义的行为。我们是应该允许这种情况发生还是边界检查并抛出异常?
另一个例子是一个带有int
参数但只允许受限域的函数:
int foo(int x)
{
if (x > 0 && x <= 10) {
return x;
}
}
如果x
不在域中,则执行将在没有return
语句的情况下到达函数的末尾 - 这会给出未定义的行为。
图书馆开发人员是否应该允许这样做?
答案 0 :(得分:3)
何时故意导致未定义的行为是公平的?
假设您从库实施者的角度提出这个问题:每当您警告您的客户未能遵守给定功能的前提条件会导致未定义的行为,并且您的客户端会破坏这些条件。
C ++ 11标准库定义了许多这样的函数:只需考虑序列集合的下标运算符。
如果你从应用程序员的角度问这个问题,另一方面,答案当然是#34;永远&#34;,除非你写的是非 - 可移植的代码,它依赖于编译器的某些记录的扩展和/或操作系统的某些功能(但是,无论你是否仍然在谈论C ++,它都是有争议的) &#34)
。图书馆开发人员是否应该允许这样做?
如果是这样的话,先生。斯蒂芬诺夫现在应该感到可怕。不,它还不错,它只取决于你的图书馆是为最高效率还是最大安全而设计的 - 中间有很多细微差别。
答案 1 :(得分:1)
这一切都归结为文档。
直观地说,你不希望[]
进行任何绑定检查,但是你也可以向你的容器提供一个at
方法抛出一个异常(就像那些写{的人一样{1}})。当然,您可以抛出异常,但记录此行为。
第二个是公平竞争,只要你清楚地记录行为是未定义的,如果使用错误的参数调用函数和你有充分的理由这样做(红色)。如果您正在设计一个性能关键型库,则不需要检查输入的开销。如果没有,请抛出异常。