std::stoul不会抛出std::out_of_range异常

4

请考虑以下代码:

#include <iostream>
#include <cstring>
#include <cerrno>

int main() {
    unsigned long num = strtoul("0xFFFFFFFFFFFF11223344556677889900AABBCCDDEEFF", NULL, 16);
    std::cout << std::strerror(errno) << "\n";
    unsigned long num2 = std::stoul("0xFFFFFFFFFFFF11223344556677889900AABBCCDDEEFF");
    std::stoul("hello world");
    return 0;
}

这段代码应该会从strerror中打印一些“超出范围”的内容,然后抛出out_of_range异常(根据文档)。它不应该到达最后的stoul语句。
实际上,在第二个stoul语句上它并没有抛出异常。我尝试过GCC 4.8.5和MinGW 8.2.0,两者都未能抛出out_of_range异常,只在最后一个stoul语句上提供了invalid_argument。
这是一个应该报告的错误吗?还是我漏掉了什么,这是预期的行为?

1
如果您想让 stoul 推断基数,您需要使用 std::stoul(..., nullptr, 0) - Holt
2
在进行操作之前不要忘记将 errno 清零(它只在失败时被写入,而不是成功 - 如果您想一次检查整个操作块,这可能很有用)。 - Toby Speight
1个回答

8

std::stoul的默认进制为10。

stoul读取字符串中的数字,遇到0时会尝试解析它后面的字符,如果是x则视为非法字符,后面的内容将被忽略,返回数值0

可以像使用strtoul一样使用类似的语法:

unsigned long num2 = std::stoul("0xFFFFFFFFFFFF11223344556677889900AABBCCDDEEFF", nullptr, 16);

或者自动推断数字基数:

unsigned long num2 = std::stoul("0xFFFFFFFFFFFF11223344556677889900AABBCCDDEEFF", nullptr, 0);

以上两个版本都会抛出异常。在线查看!


3
关键在于该函数解释字符串中的整数,而不是整个字符串本身。我认为提问者应该使用 pos 来检测这种情况,假设需要捕获错误(而不仅仅通过改变进制来避免错误)。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接