C ++标准库具有许多字符串处理功能,其中之一是std::string::substr
。
来自cplusplus.com:
返回一个新构造的字符串对象,其值初始化为该对象的子字符串的副本。
子字符串是对象的一部分,从字符位置pos开始并跨越len个字符(或直到字符串的结尾,以先到者为准)。
[一个有趣的情况是用std::string::substr
调用some_string.substr(start_pos)
,例如:
start_pos = std::string::npos
这引发异常:
在抛出'std :: out_of_range'实例后调用终止what():basic_string :: substr:__ pos(为4294967295)> this-> size()(为6)
我希望它只是返回一个空字符串。
我可以认为我们不想浪费内存来创建空字符串。还有什么?代码错过了一些健全性检查:我相信打个招呼完全没问题!
参考:
// We have a sentence.
std::string greeting = "Hello!";
// Skip the first word.
std::cout << greeting.substr(greeting.find(" "));
// Oops! "greeting" has only one word.
据说范围太广,主要基于意见。因此,我尝试提出更严格的问题(第2点和第3点)。
编辑:由于第2点和第3点有些主观,让我们尝试澄清一下:
“ Preferable”意味着其他方式应该是不直观的,并且可能是扭曲和混乱的。
示例:文件打开失败时引发例外。而不是检查它是否存在,然后将其打开。
“坏”或“有害”,如代码气味。这是龙。
示例:深度嵌套的控制流,魔术常数和重复复制的代码。
在上面的示例中,以任何方式返回空字符串是“有害”还是“不良”?
考虑这种情况:
Why does std::string::substr throw an exception instead of returning an empty string? [closed]
现在有两种情况:size_t calculate_length();
size_t calculate_pos();
std::string x{"Hello World"};
auto sub = x.substr( calculate_pos() , calculate_length() );
都返回范围内的值,并且一切都很好。如果不是,则calculate_pos
允许我识别它(我得到了例外)。
如果string::substr
会为x.substr
越界返回一个空字符串,那么当pos
时,我将无法分辨calculate_pos
越界。这似乎没有用处,但是为什么要使界面变得比必要的更为复杂呢?这样,第二个参数的任何值都可以。那是一件好事。
进一步考虑,如果您不想为潜在的例外支付费用,则不必这样做。 calculate_length() == 0
的构造函数带有两个迭代器,可以有效地实现相同的效果
std::string
没有安全网。如果您得到错误的范围,则您有不确定的行为。
根据您的需要,您可以在构造函数(您绝对确定您具有有效范围)和调用auto begin = calculate_pos();
auto end = begin + calculate_length();
std::string sub{x.begin() + begin, x.begin() + end};
(您需要范围检查)之间进行选择。但是,通常需要避免使用也可能是正确结果的前哨值(空字符串)。