L. *_* F. 1 c++ language-lawyer string-view c++17
std::string_view使用临时初始化a是一个常见的错误std::string。
using namespace std::literals;
std::string_view sv1 = "foo" ; // good
std::string_view sv2 = "bar"s; // bad: "foo"s will expire
std::cout << sv1 << "\n"       // outputs foo
          << sv2 << "\n";      // undefined behavior
这是因为"bar"s,临时表达式std::string在完整表达式的末尾被销毁了。
但是"foo"sv呢?
std::string_view sv3 = "baz"sv;
当然这应该起作用,因为后缀sv否则是没有用的。但是,这与之"baz"s有何根本区别?换句话说,为什么引入的字符串"baz"sv不过期?
sv2不好Run Code Online (Sandbox Code Playgroud)string operator""s(const char* str, size_t len);返回:
string{str, len}。
在中"foo"s,字符串文字"foo"用于初始化临时文件std::string。字符被复制到临时的基础数组std::string。std::string_view是一个非所有者视图,sv2指向临时的基础数组std::string。临时文件std::string销毁后,sv2继续指向(现已过期)基础数组,并尝试输出sv2结果导致未定义的行为。
sv3好Run Code Online (Sandbox Code Playgroud)constexpr string_view operator""sv(const char* str, size_t len) noexcept;返回:
string_view{str, len}。
因此,的声明sv3等于:1
std::string_view sv3{"baz", 3};
sv3直接指向字符串文字"baz"。字符串文字具有静态存储期限,并且不会过期。
1这里有些微妙之处。复制省略可能会或可能不会适用于此。由于string_views是非所有者,因此复制string_views不会引入新的临时字符串。因此,无论是否要进行复制,其状态sv3都相同。