尝试测试移动语义我构建了一个分配一些内存的简单类:
class CTest
{
private:
std::size_t size;
char* buffer;
public:
CTest(std::size_t size) : size(size), buffer(nullptr)
{
buffer = new char[size];
}
~CTest()
{
delete[] buffer;
}
CTest(const CTest& other) : size(other.size), buffer(nullptr)
{
buffer = new char[size];
}
CTest(CTest&& other) : size(other.size), buffer(other.buffer)
{
other.buffer = nullptr;
}
};
你可以看到它是一个非常简单的类,当它通过ref复制时,它会分配新的内存(不会复制它的内容,仅用于测试)。 移动构造函数只是使内部指针指向参数数据,没有分配新的内存。
使用带有辅助函数的Windows QueryPerformanceCounter()进行基准测试,如:
template <typename Func>
__int64 Benchmark(Func f, size_t count)
{
LARGE_INTEGER li = {};
QueryPerformanceCounter(&li);
__int64 start = li.QuadPart;
f(count);
QueryPerformanceCounter(&li);
return li.QuadPart - start;
}
非常简单的基准测试功能,保存开始时间并从结束时间中减去它并返回结果。 现在用于测试功能:
void Alloc_Ref(size_t count)
{
CTest t(1024);
for(size_t i = 0; i < count; ++i)
CTest c(t);
}
void Alloc_Move(size_t count)
{
for(size_t i = 0; i < count; ++i)
CTest c(CTest(1024));
}
Alloc_Ref使用预先初始化的变量,因此它调用复制构造函数,而Alloc_Move只使用临时类,因此它调用移动构造函数。
我打电话给这样的测试:
cout << "Ref: " << Benchmark(Alloc_Ref, 1000000) << " ms." << endl;
cout << "Move: " << Benchmark(Alloc_Move, 1000000) << " ms." << endl;
问题是,Alloc_Move没有调用移动构造函数,它继续调用复制构造函数,是否有东西丢失?
同样重要的是,当我在Alloc_Move上执行此操作时:CTest c(move(CTest(1024))
它会调用移动构造函数但是它比Alloc_Ref速度慢,还有什么东西可以丢失吗?
抱歉这篇长篇文章并提前致谢。
答案 0 :(得分:3)
问题是,
Alloc_Move
没有调用移动构造函数,它继续调用复制构造函数,是否有东西丢失?
您的分析不正确。如果您使用的是Visual C ++ 2010 SP1编译器,Alloc_Move
既不调用复制构造函数也不调用移动构造函数。声明和初始化
CTest c(CTest(1024));
转化为
CTest c(1024);
即,通过调用构造函数c
直接初始化CTest(std::size_t size)
。没有创建或销毁临时CTest
个对象。
在我的Visual Studio 2010 32位虚拟机上,我发现Alloc_Move
和Alloc_Ref
函数之间的性能差异为20%(后者更快)。我简短地看了一眼生成的组件,但没有看到任何明显的差异原因。使用Visual C ++ 11 Beta编译器(对于x86),Alloc_Move
的速度是Alloc_Ref
的两倍(我没有进一步调查,我不知道原因是什么)。< / p>
[另请注意,您的测量单位错误:QueryPerformanceCounter
不返回毫秒;它会返回滴答声。您需要致电QueryPerformanceFrequency
以获取每秒的滴答数,然后相应地划分您的测量值。]
答案 1 :(得分:-2)
为了利用移动语义,您需要显式使用rvalue引用。为了与旧代码兼容,编译器永远不会为您隐式地转换为右值引用;你需要使用std::move
或明确施放。
您Alloc_Move
的可能性较慢,因为您每次构建CTest(1024)
时都会构建新的c
,而Alloc_Ref
仅构建一个CTest(1024)
{{1}}并重复使用它。