为什么 emplace_back(“Hello") 调用 strlen? [英] Why does emplace_back("Hello") call strlen?
问题描述
贾斯汀在另一个问题上的回答 提出了一个我觉得非常有趣但无法完全解释的观察结果.考虑以下代码:
Justin's answer on another question made an observation that I find very interesting but can't quite explain. Consider the following code:
std::vector<std::string> v;
v.push_back("Hello, world!"); // Doesn't call strlen.
v.emplace_back("Hello, world!"); // Calls strlen.
如果您查看程序集,emplace_back
会生成对 strlen<的调用/code>
,而 push_back
没有(在 gcc 中测试)8.1 和 clang 6.0 使用 -Ofast
).
If you look at the assembly, emplace_back
generates a call to strlen
, whereas push_back
does not (tested in gcc 8.1 and clang 6.0 using -Ofast
).
为什么会这样?为什么 emplace_back
不能优化这里的 strlen
调用?我最初的想法是 push_back
隐式地创建了 std::string
before 函数调用(所以 std::string
构造函数直接传递字符串文字,这是最佳处理),而 emplace_back
创建 std::string
after 函数调用(所以 std::string
构造函数是 forwarded 字符串文字,我认为它已经从 const char [N]
衰减到 const char *
,因此需要一个 strlen
调用).
Why is this happening? Why can't emplace_back
optimize out the strlen
call here? My initial thought was that push_back
is implicitly creating the std::string
before the function call (so the std::string
constructor is directly passed the string literal, which is optimally handled), whereas emplace_back
creates the std::string
after the function call (so the std::string
constructor is forwarded the string literal, which I presumed had decayed from a const char [N]
to a const char *
, thus requiring a strlen
call).
但是 emplace_back
需要一个 T&&
参数 和 我的测试表明字符串文字不应该衰减到指针在这里.显然我忽略了一些东西.
But emplace_back
takes a T&&
parameter, and my tests show that the string literal shouldn't be decaying to a pointer here. Clearly I'm overlooking something.
推荐答案
strlen
调用位于慢速路径的外联函数体中;该函数体必须对 const char (&)[42]
类型的所有参数有效(在您的 Godbolt 示例中),包括并非源自 41 个字符的字符串文字且没有嵌入的参数空值.
The strlen
call is in the out-of-line function body for the slow path; that function body must be valid for all arguments of type const char (&)[42]
(in your godbolt example), including arguments that did not originate from a string literal of 41 characters with no embedded nulls.
快速路径被内联到 foo
中,并在编译时计算长度.
The fast path is inlined into foo
, and it does compute the length at compile time.
这篇关于为什么 emplace_back(“Hello") 调用 strlen?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!