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视图
类型专用于此类用途更为实际。