C++11 feature: move constructor

There are heaps of good articles out there about C++ features including this move constructor. However this one focuses on this feature helping resolve a drawback with the C++'s costly value return that has long been annoying me.

Let's have a look at the following code excerpt,

#include <cstring>
#include <utility>

class A
{
	char *_innerData;

public:
	A() : _innerData(NULL)
	{
	}

	~A()
	{
		if (_innerData)
		{
			delete[] _innerData;
		}
	}

	A(char *pszData)
	{
		int buflen = strlen(pszData)+1;
		_innerData = new char[buflen];
		strcpy(_innerData, pszData);
	}

	A(const A& other)
	{
		int buflen = strlen(other._innerData)+1;
		_innerData = new char[buflen];
		strcpy(_innerData, other._innerData);
	}

	A(A&& other)
	{
		_innerData = other._innerData;
		other._innerData = NULL;
	}

	A& operator=(const A&other)
	{
		_innerData = new char[strlen(other._innerData)+1];
		strcpy(_innerData, other._innerData);
		return (*this);
	}

public:
	char *GetData()
	{
		if (_innerData == NULL) return "<null>";
		return _innerData;
	}

public:
	static A ModA(const A &origin)
	{
		A modified = origin;
		char *pOldData = modified._innerData;
		modified._innerData = new char[strlen(pOldData)+4];
		strcpy(modified._innerData, pOldData);
		strcat(modified._innerData, "abc");
		delete[] pOldData;
		return modified;
	}
};

If we call the ModA method as below, normally we expect the value to be copied at least once from the top stack frame to the target value and the copy constructor is invoked.

A a("haha i'm the first");
A d = A::ModA(a);
printf("d = %s\n", d.GetData());

As far as there's a move constructor, the compiler enforces the move constructor being called upon the return of the suburoutine (it makes sense as the local variable will not be used) which makes the value transfer more efficient.

Lets step gack to thinking about the copy constructor. It is inefficient in this case, however it's not impossible to implemebt a shallow copy. However this is not a safe and good pratice as the user might use it assuming it's deep copy and encounter error upon deallocation. That's why move constructor comes in as a memory safe solution.

Note it only works with this pattern, defining a reference type (A& or even A&&) in this case doesn't help and is even invalid, and providing a value through a parameter of a reference type doesn't require this technique.

In general this entire new feature only helps avoid unnecessary deep copy of large internal objects on dynamically allocated memory, it doesn't eliminate copying of statically existing members since it's not a reference/pointer to the whole object.

posted @ 2013-10-03 08:38  quanben  阅读(489)  评论(0编辑  收藏  举报