C++ std::string::compare(const char*)能否引发异常?
这是过载(4) 在“异常”部分中,重载2、3、5、6(具有pos1和/或pos2参数)被命名为抛出C++ std::string::compare(const char*)能否引发异常?,c++,language-lawyer,C++,Language Lawyer,这是过载(4) 在“异常”部分中,重载2、3、5、6(具有pos1和/或pos2参数)被命名为抛出std::out_of_range 重载(4)没有“pos”参数,但未标记为noexcept 它是否抛出,取决于实现吗 在GCC7的libstdc++中,它调用char\u traits::length和char\u traits::compare。除了析构函数、交换函数、移动构造函数和移动赋值运算符之外,这些函数似乎不能抛出,但没有标记为noexcept,标准仅在函数有一个,即没有先决条件时才标记
std::out_of_range
重载(4)没有“pos”参数,但未标记为noexcept
它是否抛出,取决于实现吗
在GCC7的libstdc++中,它调用
char\u traits::length
和char\u traits::compare
。除了析构函数、交换函数、移动构造函数和移动赋值运算符之外,这些函数似乎不能抛出,但没有标记为noexcept
,标准仅在函数有一个,即没有先决条件时才标记函数noexcept
。此重载要求参数为以null结尾的字符串,因此标准不会将其标记为noexcept
rational的定义如下:
标记为noexcept
的函数很难测试
当函数标记为noexcept
时,就无法标记测试失败,
特别是在测试驱动程序中,通过抛出异常。一个常见的例子是代码
在进入函数时验证先决条件的:
T& std::vector<T>::front() noexcept {
assert(!this->empty());
return *this->data();
}
T&std::vector::front()无例外{
断言(!this->empty());
返回*此->数据();
}
当验证来自测试驱动程序的此类防御检查时,一种合理的方法是
注册一个断言处理程序,该处理程序抛出一个定义良好的违反前提条件的异常,
测试驱动程序捕捉到的,以确保正确的断言
s确实处于
地点
现在我们可能会认为,当向量为
空,是未定义的行为,因此我们不应期望任何保证。问题是库正在指定未定义的行为;对于编译器来说,这段代码是
定义良好,如果assert
抛出异常,程序必须终止
以明确规定的方式挫败测试驾驶员
请注意,这里的问题并不是我们使用断言来查找我们自己的错误
库实现,而不是错误地调用库的用户代码。
如果我们取消了测试这些防御断言的能力,我们可能会弄错,
从而使我们的用户面临犯下比传播更严重错误的风险
意外的例外
顺便说一下,由于:
实现可以通过添加非抛出异常规范来加强非虚拟函数的异常规范
libstdc++
和libc++
可以自由标记这个重载noexcept
老实说,我不知道为什么这个问题会得到这么多的赞成票Clang
的格式为:int-compare(const-value\u-type*\u-s)const-NOEXCEPT代码>GCC也是如此:int compare(const\u CharT*\u s)const\u GLIBCXX\u NOEXCEPT
看起来取决于实现,但从逻辑上看,它应该是noexcept
。我想我们需要一个语言律师来获得真正的答案……但我假设,标准不要求std::string
将字符串存储为图表*
,以便允许小字符串优化。然而,这也意味着我们可能需要进行一些转换,以实现实际的比较。此转换可能需要分配内存,内存可能会耗尽,因此可能会抛出。因此,标准无法从实现中强制执行noexcept
,尽管在实践中它们仍然可能是noexcept
。