为什么 emplace_back(“Hello") 调用 strlen? [英] Why does emplace_back("Hello") call strlen?

查看:35
本文介绍了为什么 emplace_back(“Hello") 调用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆