为什么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
会生成对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
,它确实在编译时计算长度。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么emplace_back("Hello")调用strlen?
- 调用 backtrace_symbols_fd() 有时会在 snprintf 中调用 strlen 时挂起