字符串未针对字符串文字进行优化

P. *_*tos 13 c++ string stl

在我的C++项目中,我在更换所有内容之前迈出了一步char*,std::string但我发现某个特定场合std::string失败了.

想象一下,我有这两个功能:

void foo1(const std::string& s)
{
    ...
}

void foo2(const char* s)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果我写这样的东西:

const char* SL = "Hello to all!";

foo1(SL); // calls malloc, memcpy, free
foo2(SL);
Run Code Online (Sandbox Code Playgroud)

foo1所述SL将隐式转换成std::string.这意味着std::string构造函数将分配内存,并将字符串文字复制到该缓冲区.在foo2虽然没有所有这些都不会发生.

在大多数实现std::string中应该是超级优化的(例如Copy On Write)但是当我用const char*它构造它时它不是.我的问题是:为什么会这样?我错过了什么吗?我的标准库是不是足够优化还是出于某种原因(我不知道)这是完全不安全的?

Mat*_* M. 21

实际上,如果你更改了文字,你的担忧就会消失(*):

std::string const SL = "Hello to all!";
Run Code Online (Sandbox Code Playgroud)

const为你加了.

现在,呼叫foo1将不涉及任何复制(根本),并且foo2可以以很少的成本实现呼叫:

foo1(SL);         // by const-reference, exact same cost than a pointer
foo2(SL.c_str()); // simple pointer
Run Code Online (Sandbox Code Playgroud)

如果要移动std::string,不仅要切换功能接口,还要切换变量(和常量).

(*)假设原始答案SL是全局常量,如果它是函数的局部变量,那么static如果真的希望避免在每次调用时构建它,则可以进行.

  • 这是不是意味着你的所有字符串文字都会在启动时被复制到堆中? (4认同)

Kar*_*nek 10

问题是std :: string类无法识别const char*指针是否是全局字符文字:

const char *a = "Hello World";
const char *b = new char[20];
Run Code Online (Sandbox Code Playgroud)

char*指针可能在任何时候都无效(例如,当它是局部变量且函数/范围结束时),因此std::string必须成为字符串的独占所有者.这只能通过复制来实现.

以下示例说明了为什么有必要:

std::string getHelloWorld()  {
  char *hello = new char[64];
  strcpy(hello, "Hello World");
  std::string result = (const char *)hello;  // If std::string didn't make a copy, the result could be a garbage
  delete[] hello;
  return result;
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么`新'?在堆栈上分配缓冲区也可以:`char const hello [] ="Hello World";` (2认同)

jal*_*alf 5

std::string不是银弹.它旨在成为拥有其内存的通用可变字符串的最佳实现,并且使用C API相当便宜.这些是常见的场景,但它们与字符串使用的每个实例都不匹配.

正如您所提到的,字符串文字不适合这个用例.它们使用静态分配的内存,因此std::string不能也不应该尝试占用内存.并且这些字符串始终是只读的,因此std::string不允许您修改它们.

std::string 创建传递给它的字符串数据的副本,然后在内部处理此副本.

如果你想操作其生命周期在别处处理的常量字符串(在字符串文字的情况下,它由初始化和释放静态数据的运行时库处理),那么你可能想要使用不同的字符串表示.也许只是一个简单的const char*.