为什么 std::string 的复制构造函数看起来比它的移动副本更快?
Why does the copy constructor for std::string appear to be faster than its move counterpart?
我正在尝试学习移动语义,我读到移动可能比复制更快。但是,对于以下微不足道的代码,我的看法恰恰相反:
for (int i = 0; i < 100000000; ++i) {
std::string a("Copy");
std::string b = a;
}
for (int i = 0; i < 100000000; ++i) {
std::string a("Move");
std::string b = std::move(a);
}
这是我 mac:
花费的时间
$ time ./copy.out
real 0m2.511s
user 0m2.481s
sys 0m0.011s
$ time ./move.out
real 0m3.993s
user 0m3.933s
sys 0m0.020s
正如其中一条评论所暗示的那样,大多数库实现都执行 "short string optimization",SSO,其中对于足够短的字符串(对于给定的实现,有一些特定的长度),整个字符串都存储在正文中字符串对象,在堆栈上。当您的数据完全存储在堆栈中时,移动与复制相同。我所知道的所有实现都会 SSO 一个 4 字符的字符串,所以无论您是移动还是复制它都几乎是相同的操作。
如果输出sizeof(sring)
的结果,选择比它大的字符串,两种情况都使用相同的字符串。还要确保优化已开启。
这种微基准测试方法不是很好。通常最好在定时区域之外随机化数据,然后在定时循环中执行操作。使用相同的常量数据通常会导致疯狂的编译器优化,从而使您的结果无效。
我正在尝试学习移动语义,我读到移动可能比复制更快。但是,对于以下微不足道的代码,我的看法恰恰相反:
for (int i = 0; i < 100000000; ++i) {
std::string a("Copy");
std::string b = a;
}
for (int i = 0; i < 100000000; ++i) {
std::string a("Move");
std::string b = std::move(a);
}
这是我 mac:
花费的时间$ time ./copy.out
real 0m2.511s
user 0m2.481s
sys 0m0.011s
$ time ./move.out
real 0m3.993s
user 0m3.933s
sys 0m0.020s
正如其中一条评论所暗示的那样,大多数库实现都执行 "short string optimization",SSO,其中对于足够短的字符串(对于给定的实现,有一些特定的长度),整个字符串都存储在正文中字符串对象,在堆栈上。当您的数据完全存储在堆栈中时,移动与复制相同。我所知道的所有实现都会 SSO 一个 4 字符的字符串,所以无论您是移动还是复制它都几乎是相同的操作。
如果输出sizeof(sring)
的结果,选择比它大的字符串,两种情况都使用相同的字符串。还要确保优化已开启。
这种微基准测试方法不是很好。通常最好在定时区域之外随机化数据,然后在定时循环中执行操作。使用相同的常量数据通常会导致疯狂的编译器优化,从而使您的结果无效。