3

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, 临时, 在full-expressionstd::string结束时被销毁。

但是怎么样"foo"sv

std::string_view sv3 = "baz"sv;

当然这应该可行,因为后缀sv在其他情况下是无用的。但这与 有何根本不同"baz"s?也就是说,为什么引入的字符串"baz"sv不会过期?

4

1 回答 1

8

为什么声明sv2不好

[basic.string.literals]/1

string operator""s(const char* str, size_t len);

回报: string{str, len}

"foo"s中,字符串文字"foo"用于初始化一个临时的std::string. 字符被复制到临时的底层数组中std::stringstd::string_view是一个非拥有视图,并sv2指向临时的底层数组std::string。临时std::string对象被销毁后,sv2继续指向(现已过期)底层数组,并尝试输出sv2导致未定义的行为。

为什么声明sv3是好的

[string.view.literals]/1

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都是相同的。

于 2019-05-18T02:00:16.560 回答