为什么在分配给const std :: string时复制字符串文字?

时间:2018-11-09 01:58:49

标签: c++ string optimization copy string-literals

根据cppreference.com,当从输入const std::string(例如const char*)构造const std::string("some literal");时,C字符串的副本存储在std::string中。

我试图了解在输入C字符串是字符串文字的情况下是否(以及为什么)需要复制。我认为std::string可以只引用字符串文字,而不用创建副本,因此以下代码将只创建一次"some literal"

std::string str1("some literal");
std::string str2("some literal");

当然,对不是字符串文字的C字符串执行复制是明智的,因为它允许std::string管理所引用数据的生存期。但是,这对于字符串文字不是问题,因为它们在程序的整个生命周期内存在。

此外,由于我们在谈论const字符串,因此我们不必担心基础数据在程序执行过程中会发生变化并且不会破坏std::string的值语义。好吧,至少只要不使用const_cast,但无论如何,使用const_cast都会带来麻烦,所以我不太担心这种情况。

因此,为什么没有任何理由使编译器无法优化这种情况,以使const std::string引用const char*而不是创建副本?或者,如果cppreference链接不正确,并且此优化实际上是由某些编译器实现的,则哪些编译器支持此功能?

出于这个问题,我们假设字符串文字足够长,以至于小的字符串优化不会成为一个因素。

1 个答案:

答案 0 :(得分:1)

在您的示例中,std::string仅接收一个指针,它无法知道该指针实际指向的是哪种内存。

将指针声明为指向const数据这一事实无关紧要。可以将指向非const数据的指针分配给指向const数据的指针(创建对可写数据的只读访问)。

std::string根本无法知道给定的指针指向字符串文字。指针可以很容易地指向调用堆栈上的数组,指向new分配的内存块或外部库拥有的内存。

狭窄的字符串文字没有什么特别的,std::string不能为它调整其行为。它只是普通的const char[],只是一个由编译器/链接器设置其内存的地址。它衰减到const char *

在缺乏原始信息的情况下,std::string会做的唯一明智而安全的事情-制作数据副本。

这也使实现保持简单-std::string始终拥有其拥有的数据。

如果您想要一个不拥有数据的类似字符串的容器,只需指向它,然后查看C ++ 17的std::string_view或早期编译器的boost::string view