晚上在小屋里,亲爱的程序员。
我阅读了一篇关于移动语义、对 r-value 和 std::move() 的引用的文章,之后我很高兴地检查了通过快速而懒惰地编写两个冒泡排序实现可以获得多少时间:
#include <iostream>
#include <utility>
#include <ctime>
#include <cstdlib>
template <typename T>
bool check(T* arr, int n)
{
for (int i = 0; i < n - 1; i++)
{
if (arr[i] > arr[i + 1]) return 0;
};
return 1;
}
template <typename T>
void bubblesortcopy(T* arr, int n)
{
while (true)
{
bool op = false;
for (int j = 0; j < n - 1; j++)
{
if (arr[j + 1] < arr[j])
{
T h = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = h;
op = true;
};
};
if (!op) return;
n--;
};
};
template <typename T>
void bubblesortmove(T* arr, int n)
{
while (true)
{
bool op = false;
for (int j = 0; j < n - 1; j++)
{
if (arr[j + 1] < arr[j])
{
T h { std::move(arr[j + 1]) };
arr[j + 1] = std::move(arr[j]);
arr[j] = std::move(h);
op = true;
};
};
if (!op) return;
n--;
};
};
int main()
{
int n;
clock_t start;
clock_t end;
std::cin >> n;
int* arr1 = new int[n];
int* arr2 = new int[n];
for (int i = 0; i < n; i++)
{
arr1[i] = rand();
arr2[i] = arr1[i];
};
start = clock();
bubblesortcopy(arr1, n);
end = clock();
if(check(arr1, n)) std::cout << difftime(end, start) / CLOCKS_PER_SEC << std::endl;
start = clock();
bubblesortmove(arr2, n);
end = clock();
if(check(arr2, n)) std::cout << difftime(end, start) / CLOCKS_PER_SEC << std::endl;
delete[] arr1;
delete[] arr2;
};
结果,期望和现实大相径庭:
向菜鸟解释什么是错的?或者它是一个特性而不是一个错误?

所以你“移动”了通常的
int-s!类型int具有移动语义 - 这是复制语义。难怪什么都没有改变。(我怀疑您在代码的调试版本中测量了时间,因此据称它甚至变慢了。在代码的调试版本中测量时间是没有意义的。)某种“加速”移动语义只能在主要为管理内部资源的对象编写的用户代码级别(在移动构造函数和移动赋值运算符内部)才有可能。在绝大多数情况下,基于移动语义的“加速”是基于这样一个事实,即对于具有多级内部结构的类型,浅拷贝(浅拷贝)比深拷贝(深拷贝)更快。
例如,类型
std::vector是具有“深”内部结构的类型(它通常存储指向内部元素数组的指针)并且具有由库作者实现的非平凡移动语义。再试一次相同的实验,T == std::vector而不是T == int。看看会发生什么。采取更长的阵列。(选项 cT == std::string可能会或可能不会用于此目的,因为某些实现std::string通过引用计数实现复制。)当然,所有这些都与type
int无关。对于类型int移动是复制。对于所有基本类型,移动都是正常的副本。对于所有“平面”类型,移动只是复制。那些。例如,对于类型您也不会从移动语义中获得任何加速。
再一次:非平凡(即非复制匹配)移动语义始终是用户/库级别的功能。那些。移动语义总是手工编写的,以移动构造函数和移动赋值运算符的形式。所有这些都是由您自己或图书馆作者编写的。如果您没有编写类似的东西,那么您的代码就没有任何重要的移动语义。从您应用它的事实来看,
std::move它不会出现在任何地方。std::move- 它只是一个演员表,它“什么都不做”。在我的机器上,VC++2017 启用了
n == 2000050 次实验的优化那些。在误差范围内 - 重合...
QED,因为对于
int语义移动 == 语义复制...现在我们更改
int为string, 并生成每个 100 个字符的随机字符串进一步 - 一切都一样,只有 10000 个数组,以免等那么久:)
基于 14 次实验的结果(仍然缺乏耐心):
结果不言自明:)