【发布时间】:2018-07-07 03:53:49
【问题描述】:
Justin's answer 在另一个问题上做了一个我觉得很有趣但不能完全解释的观察。考虑以下代码:
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,而 push_back does not(在 gcc 8.1 和 clang 6.0 中使用 -Ofast 测试)。
为什么会这样?为什么emplace_back 不能在这里优化strlen 调用?我最初的想法是 push_back 隐式创建 std::string before 函数调用(因此 std::string 构造函数直接传递字符串文字,这是最佳处理),而 emplace_back在函数调用之后创建std::string (所以std::string 构造函数被转发字符串文字,我认为它已经从const char [N] 衰减到@987654340 @,因此需要strlen 调用)。
但是emplace_back takes a T&& parameter 和my tests show that the string literal shouldn't be decaying to a pointer here。显然我忽略了一些东西。
【问题讨论】:
-
您是否注意到
strlen()调用仅在需要调整矢量大小时发生?在size() < capacity()的正常情况下,不会调用strlen()。所以在性能方面这并没有什么区别,因为只有慢速路径有strlen()调用,而且由于许多其他原因它很慢。 -
@BasileStarynkevitch:不只是 GCC。 clang 和 libc++ 也会发生同样的事情。我问是因为我很好奇。
-
@Cornstalks:那么我认为接下来你应该阅读汇编代码并弄清楚编译器在调用
strlen()时正在做什么。 -
并非所有
const char [N]s 都是字符串文字。 -
而且你不能假设
const char [N]不会有'\0'之前结束。