为什么emplace_back("Hello")调用strlen?

Why does emplace_back("Hello") call strlen?

本文关键字:调用 strlen Hello 为什么 back emplace      更新时间:2023-10-16

贾斯汀对另一个问题的回答提出了一个我觉得非常有趣但无法完全解释的观察结果。请考虑以下代码:

std::vector<std::string> v;
v.push_back("Hello, world!");  // Doesn't call strlen.
v.emplace_back("Hello, world!");  // Calls strlen.

如果您查看程序集,emplace_back会生成对strlen的调用,而push_back则不会(使用-Ofast在 gcc 8.1 和 clang 6.0 中进行测试(。

为什么会这样?为什么emplace_back不能在这里优化strlen调用?我最初的想法是,push_back在函数调用之前隐式创建std::string(因此std::string构造函数直接传递字符串文字,这是最佳处理的(,而emplace_back在函数调用创建std::string(因此std::string构造函数转发字符串文字,我认为它已经从const char [N]衰减到const char *, 因此需要strlen调用(。

但是emplace_back需要一个T&&参数,我的测试表明字符串文字不应该衰减到这里的指针。显然我忽略了一些东西。

strlen调用位于慢速路径的外行函数体中;该函数体必须对const char (&)[42]类型的所有参数(在您的 Godbolt 示例中(有效,包括不是源自 41 个字符的字符串文本且没有嵌入 null 的参数。

快速路径被内联到foo,它确实在编译时计算长度。