trying to test out move semantics i build a simple class that allocates some memory:
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;
}
};
as you can see its a very simple class that when it copies by ref it allocates new memory (doesnt copy its contents tho, just for testing).
and the move constructor just makes the internal pointer pointing to the argument data, no new memory is allocated.
for benchmarking im using windows QueryPerformanceCounter() with a helper function like:
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;
}
very simple benchmark function, saves the starting time and subtracts it from the ending time and returns the result.
now for the testing functions:
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));
}
the Alloc_Ref one uses a pre-initialized variable so it calls the copy constructor and the Alloc_Move one simply uses a temporary class, so it calls the move constructor.
im calling the test like this:
cout << "Ref: " << Benchmark(Alloc_Ref, 1000000) << " ms." << endl;
cout << "Move: " << Benchmark(Alloc_Move, 1000000) << " ms." << endl;
problem is, Alloc_Move is not calling the move constructor, it continues to call the copy constructor, is there something im missing?
also equally important, when i do this on the Alloc_Move: CTest c(move(CTest(1024)) it does call the move constructor BUT its slower than the Alloc_Ref one, again is there something im missing?
sorry the long post and thanks in advance.
In order to take advantage of move semantics, you need to explicitly use rvalue references. For compatibility with older code, the compiler will never implicitly cast to an rvalue reference for you; you need to either use
std::moveor explicitly cast.Your
Alloc_Moveis most likely slower because you’re constructing a newCTest(1024)each time you constructc, where asAlloc_Refonly constructs a singleCTest(1024)and reuses it.