C++ 为什么在分配给const std::string时会复制字符串文字?
根据,当从输入C++ 为什么在分配给const std::string时会复制字符串文字?,c++,string,optimization,copy,string-literals,C++,String,Optimization,Copy,String Literals,根据,当从输入const char*构造const std::string时(例如const std::string(“某个文本”);),C字符串的副本存储在std::string中 我试图理解在输入C字符串是字符串文字的情况下是否(以及为什么)特别需要复制。我认为std::string可以简单地引用字符串文本而不是创建副本,因此下面的代码只创建一次“some literal” std::string str1("some literal"); std::string str2("some li
const char*
构造const std::string
时(例如const std::string(“某个文本”);
),C字符串的副本存储在std::string
中
我试图理解在输入C字符串是字符串文字的情况下是否(以及为什么)特别需要复制。我认为std::string
可以简单地引用字符串文本而不是创建副本,因此下面的代码只创建一次“some literal”
std::string str1("some literal");
std::string str2("some literal");
当然,为不是字符串文字的C字符串执行复制是明智的,因为它允许std::string
管理它引用的数据的生存期。但是,这不是字符串文字的问题,因为它们存在于程序的生命周期中
另外,由于我们讨论的是const
strings,因此我们不必担心底层数据在程序中被更改,也不必破坏std::string
s的值语义。好吧,至少只要不使用const\u cast
,但是使用const\u cast
无论如何都是自找麻烦,所以我不太担心这种情况
那么,编译器为什么不能优化这种情况,使const std::string
s引用const char*
s而不是创建副本呢?或者,如果cppreference链接不正确,并且此优化实际上是由某些编译器实现的,那么哪些编译器支持此功能
对于这个问题,让我们假设字符串文字足够长,小字符串优化不会成为一个因素。在您的示例中,
std::string
只接收一个指针,它无法知道指针实际指向的内存类型
指针被声明为指向常量数据的事实与此无关。可以将指向非常量数据的指针指定给指向常量数据的指针(创建对其他可写数据的只读访问)
std::string根本无法知道它所给出的指针是否指向字符串文本。指针可以很容易地指向调用堆栈上的数组,或者指向分配了new
的内存块,或者指向外部库拥有的内存
窄字符串文本没有什么特别之处,它不是某种神奇的类型,std::string
可以调整它的行为。它只是一个普通的常量char[]
,它的内存由编译器/链接器设置。它衰减为常量字符*
因此,std::string
在缺少原始信息的情况下,它能做的唯一明智和安全的事情就是复制数据
这也保持了实现的简单性,std::string
始终拥有它所持有的数据
如果您想要一个不拥有数据的类似字符串的容器,只需指向它,然后查看C++17或早期的编译器 允许
std::string
存储字符串文字将意味着另一条信息和逻辑,以了解该字符串是否需要释放销毁时保留的内存。看看std::string\u view
@tkausl,听起来很接近答案。这很公平。我在想,既然编译器知道输入是字符串文字,它可能能够控制行为。但我还没有真正想过如何实现这一点。除此之外,如果文本字符串来自外部动态库,则在卸载库时,文本的内存将倾向于卸载,即使应用程序仍在运行,并且我们运行到UB。此外,可以说,类不一定知道它将被构造为只读对象,因此当它将被实例化为const对象时,在std::string
的构造函数中没有特殊情况。如果您想让它“意识到”在某些情况下只用于只读目的,那么它往往需要一个单独的类/类型。。。。。。特定的上下文包括在它的ctor中,比如std::const\u string
。一般来说,将string\u视图
类型专用于此类用途更为实际。