这个表达有效吗?

Is this expression valid?

我遇到过这段代码:

std::string str;
std::getline(std::cin, str);
std::string sub = str.substr(str.find('.') + 1);

第一反应是——这是无效代码。但是想了想,似乎并没有那么简单。那么它是有效的 C++ 表达式吗(具有可预测的行为)?

PS 如果不是很清楚,问题主要与 '.' 时会发生什么有关。在 str 中找不到,但不限于此,因为可能存在其他问题。

str.find('.') returns 字符在字符串中第一次出现的索引。 substr 带有一个参数 returns 从给定索引开始的字符串的后缀。因此,该行的作用是 returns 从第一个点之后开始的字符串尾部。所以如果 str"hello.good.bye"sub 将是 good.bye

但是,如果字符串实际上不包含任何点, 代码可能存在问题。它将 return 整个字符串。这可能是有意的,也可能不是。发生这种情况是因为如果没有点,find 将 return npos,这是 std::string::size_type 可以容纳的最大数字。向其中添加 1,您将得到 0(这就是无符号类型的行为方式,模 2n)。

所以代码总是有可预测的行为。

http://en.cppreference.com/w/cpp/string/basic_string/npos看来std::string::npos = -1;。当 find 不成功时,该值被 returned。在这种情况下,str.substr(0) 将 return 整个字符串。

看起来它是有效且可预测的代码。

如果您问的是找不到 . 会发生什么,您不必担心。 std::string::find 然后 returns std::string::npos,标准定义为 -1,添加 1 后溢出并使参数 0 :

std::string sub = str.substr(0);

这给了你整个字符串。我不知道这是否是所需的行为,但这肯定不是未定义的行为。

据我所知,它是有效的,尽管它不是特别可读。

如果 str 为空,则 find() 方法将 return std::string::npos。这相当于std::size_type可表示的最大unsigned int。通过向其添加 1,您将导致整数溢出,并且它将回绕到 0。这意味着 substr() 方法正在尝试使用从位置 0 到字符串末尾的字符创建一个字符串。如果 str 为空,则 sub 也为空。

实际上,在这种特定情况下——因为包含“...无关紧要...”的字符串确实如此——find() 调用不会找到它要查找的内容return std::string::npos 也会如此。然后你给这个加 1。

npos 是 std::string::size_type 类型,通常是 size_t,通常是某种无符号整数。

npos 定义为 size_type.

的最大可能值

size_type 是无符号的,最大可能值加 1 得到 0。

所以你打电话给 std::string::substr(0)。这是做什么的?它会创建您调用它的整个字符串的副本,因为 substr 需要一个起始位置和长度(默认为 npos,或 "all the way to the end")。