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

Why does emplace_back("Hello") call strlen?

在另一个问题上做了一个我觉得很有趣但无法完全解释的观察。考虑以下代码:

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

如果您查看程序集,emplace_back generates a call to strlen, whereas push_back does not(使用 -Ofast 在 gcc 8.1 和 clang 6.0 中测试)。

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

但是emplace_back takes a T&& parameter, and my tests show that the string literal shouldn't be decaying to a pointer here。显然我忽略了一些东西。

strlen 调用在慢路径的外联函数体中;该函数体必须对 const char (&)[42] 类型的所有参数有效(在您的 godbolt 示例中),包括并非源自 41 个字符的字符串文字且没有嵌入空值的参数。

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