如果我具有以下两个功能:
std::string tolower(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return static_cast<unsigned char>(std::tolower(static_cast<unsigned char>(c))); });
return s;
}
std::string_view tolower2(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return static_cast<unsigned char>(std::tolower(static_cast<unsigned char>(c))); });
return s;
}
Run Code Online (Sandbox Code Playgroud)
唯一的区别是它们的返回值。
这些功能的结果是:
// returns "test" - expected
std::cout << tolower("TeSt") << std::endl;
// returns " est" - not expected
std::cout << tolower2("TeSt") << std::endl;
Run Code Online (Sandbox Code Playgroud)
为什么有区别?
因为在第一个示例中,您只是返回并使用了一个字符串(既好又安全)。
在第二个示例中,您可能(参见下文)通过不再存在的本地字符串返回视图,因此该视图“悬空”并且您的程序具有未定义的行为。
显然,在您的情况下,函数返回机制和/或字符串破坏机制的某些部分已覆盖了以前用作字符串缓冲区的第一个字符。
[expr.call/7]:[..]由参数定义的生存期在其定义的函数返回时或在封闭的全表达式结束时结束,由实现定义。[..]