C++ 为什么sv后缀引入的字符串没有过期?

C++ 为什么sv后缀引入的字符串没有过期?,c++,language-lawyer,c++17,string-view,C++,Language Lawyer,C++17,String View,使用临时std::string初始化std::string\u视图是一个常见错误 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 << sv

使用临时
std::string
初始化
std::string\u视图是一个常见错误

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
当然,这应该是可行的,因为后缀
sv
在其他方面是无用的。但这与baz的本质区别是什么呢?换句话说,为什么
“baz”sv
引入的字符串没有过期?

为什么
sv2
的声明不正确 Per:

返回:
string{str,len}

“foo”s
中,字符串文字
“foo”
用于初始化临时
std::string
。这些字符被复制到临时
std::string
的底层数组中
std::string_视图
是一个非所有者视图,
sv2
指向临时
std::string
的底层数组。在临时
std::string
被销毁后,
sv2
一直指向(现在已过期)的底层数组,试图输出
sv2
会导致未定义的行为

为什么
sv3
的声明是好的 Per:

返回:
字符串视图{str,len}

因此,
sv3
的声明相当于:1

sv3
直接指向字符串literal
“baz”
。字符串文字具有静态存储持续时间,不会过期


这里有一些微妙之处。复制省略或在此处应用。由于
string\u视图
s是非所有者,因此复制
string\u视图
s不会引入新的临时字符串。因此,无论是否进行复制,
sv3
的状态都是相同的。

即使没有复制省略
sv3
也是安全的,因为看不到堆或堆栈。在没有省略的情况下,使用来自可执行文件本身的数据创建一个非所有者临时文件,我们称之为“全局数据”。当它的指针/大小被复制到函数边界上的
sv3
时,临时文件将被销毁,但是,由于它不是拥有的,因此不会释放内存,因为它始终是二进制文件中某个段的一部分。所以现在
sv3
是一个安全的内存视图。@MarcinZdun是的。复制省略不是这里最重要的一点。关键是字符串视图是直接从字符串文本初始化的,而不是临时的
std::string
。也就是说,无视C++17保证了复制省略这一事实感觉很奇怪:)@L.F.我同意复制省略很好,但您如此强调它,以至于听起来需要复制省略才能使“
sv3
直接指向字符串literal
“baz”
”语句true。现在你读到:“为什么sv3的声明是好的->因此,通过保证拷贝省略(…)”。因此,接下来的问题是“字符串视图副本如何?”我们都知道它们也直接指向静态
“baz”
。我要声明“字符串文字具有静态存储持续时间且不会过期。”首先回答标题问题,然后留下关于复制省略的备注。@R2RT好吧,我部分同意您的评论。首先,我只是在分析底层流程,而复制省略是其中一个步骤。我们不应该仅仅因为它听起来很花哨就歧视它;-)但你是对的,我太强调它了,我的措辞表明,省略复制对于
sv3
的工作至关重要。我已经更新了我的答案,以消除这种潜在的不准确。让我补充:(如果函数未内联,则不要)
std::string_view sv3 = "baz"sv;
string operator""s(const char* str, size_t len);
constexpr string_view operator""sv(const char* str, size_t len) noexcept;
std::string_view sv3{"baz", 3};