为什么sv后缀引入的字符串不会过期?
Why does the string introduced by the sv suffix not expire?
用临时 std::string
初始化 std::string_view
是一个常见的错误。
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
的声明是错误的
string operator""s(const char* str, size_t len);
Returns: string{str, len}
.
在"foo"s
中,字符串文字"foo"
用于初始化临时std::string
。字符被复制到临时std::string
的底层数组中。 std::string_view
是一个non-owning视图,sv2
指向临时std::string
的底层数组。临时 std::string
被销毁后,sv2
继续指向(现已过期)底层数组,并尝试输出 sv2
导致未定义的行为。
为什么sv3
的声明是好的
constexpr string_view operator""sv(const char* str, size_t len) noexcept;
Returns: string_view{str, len}
.
因此,sv3
的声明等价于:1
std::string_view sv3{"baz", 3};
sv3
直接指向字符串文字"baz"
。字符串文字具有静态存储期限并且不会过期。
1 这里有一些微妙之处。复制省略 or may not 在此处应用。由于 string_view
s 是 non-owning,复制 string_view
s 不会引入新的临时字符串。因此,无论是否进行复制,sv3
的状态都是一样的。
用临时 std::string
初始化 std::string_view
是一个常见的错误。
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
的声明是错误的
string operator""s(const char* str, size_t len);
Returns:
string{str, len}
.
在"foo"s
中,字符串文字"foo"
用于初始化临时std::string
。字符被复制到临时std::string
的底层数组中。 std::string_view
是一个non-owning视图,sv2
指向临时std::string
的底层数组。临时 std::string
被销毁后,sv2
继续指向(现已过期)底层数组,并尝试输出 sv2
导致未定义的行为。
为什么sv3
的声明是好的
constexpr string_view operator""sv(const char* str, size_t len) noexcept;
Returns:
string_view{str, len}
.
因此,sv3
的声明等价于:1
std::string_view sv3{"baz", 3};
sv3
直接指向字符串文字"baz"
。字符串文字具有静态存储期限并且不会过期。
1 这里有一些微妙之处。复制省略 string_view
s 是 non-owning,复制 string_view
s 不会引入新的临时字符串。因此,无论是否进行复制,sv3
的状态都是一样的。