C++11模板句柄的实现:委派构造函数、default关键字分析

C++11,使用委派构造函数,并且快速初始化变量,default关键字重声明默认构造函数,回复pod状态。分析与推荐用法。

目前为止,VS2012和2013对异常声明的兼容还是停留在代码沟通的级别,没有进行编译类型检查,出现如下错误可忽略。

warning C4290: 忽略 C++ 异常规范,但指示函数不是 __declspec(nothrow)


下为:VS2012不支持委托构造函数,建议使用cocos2d-x 3.2及版本的朋友更新VS至2013版。

1>d:\cpp_lab\testqueue_16th_2\testqueue_16th_2\handle.hpp(9): error C2614: “Handle<T>”: 非法的成员初始化:“Handle<int>”不是基或成员

同时VS2012也不支持快速初始化变量。



VS2013同时完成了对于default声明,但是如果考虑和委派构造函数一起使用的话,则会有如下的错误:

<span>Handle() = default{}</span><span style="font-family: Arial, Helvetica, sans-serif;">:Handle(p,new std::size_t(1))</span><span>;</span>

1>d:\cpp_2013\testqueue_16th_2\testqueue_16th_2\handle.hpp(7): error C2143: 语法错误 : 缺少“;”(在“:”的前面)

编译时出现语义上的二义性。要重新定义=():()形式的语义?

此外,一旦使用default关键字去重定义默认的构造函数使其回复至pod状态,要记得不能定义函数体,默认构造函数是由编译器合成的。若定义了default构造函数的函数体,则会出现重载定义无法识别的编译报错。

VS2013版源码如下:

class Handle
{
public:
<span>	Handle() = default; // 不能声明函数体</span>
	Handle(T *p = nullptr):Handle(p,new std::size_t(1))
	{
	}


	Handle(const Handle & h):Handle(h.m_pPtr,h.m_pUseCount)//委托构造函数,将先调用目标构造函数,再完成初始化
	{
		
	}

	Handle & operator = (const Handle & other);


	T & operator *() throw (std::runtime_error);
	T * operator ->() throw (std::runtime_error);

	T & operator *() const throw (std::runtime_error);
	T * operator ->() const throw (std::runtime_error);

	~Handle(void)
	{
		rem_ref();
	}

private:
	Handle(T*p,size_t * use):m_pPtr(p),m_pUseCount(use) // 目标构造函数
	{
		if (m_pPtr==nullptr)
		{
			 delete m_pUseCount;
			 m_pUseCount = nullptr;
		}
<span style="font-family: Arial, Helvetica, sans-serif;"><span>				</span>else</span>
<span style="font-family: Arial, Helvetica, sans-serif;"><span>				</span>{</span>
<span style="font-family: Arial, Helvetica, sans-serif;">					</span><span style="font-family: Arial, Helvetica, sans-serif;">++(*m_pUseCount);</span>
</pre><pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif;"><span>				</span>}</span>
	};

	void rem_ref()
	{
		if (--*m_pUseCount == 0)
		{
			delete m_pPtr;
			delete m_pUseCount;
			m_pPtr = nullptr;
			m_pUseCount = nullptr;
		}
	}

private:
	T * m_pPtr = nullptr;//实际上这个赋值没太多意思
<span>	</span>size_t * m_pUseCount = nullptr;

};


template <typename T>
Handle<T> & Handle<T>::operator = (const Handle<T> & other)
{
	++other.m_pUseCount;
	rem_ref();
	m_pPtr = other.m_pPtr;
	m_pUseCount = other.m_pUseCount;
	return *this;
}


template <typename T>
inline T & Handle<T>::operator *()
{
	if (m_pPtr!=nullptr)
	{
		return *m_pPtr;
	}
	else
	{
		throw std::runtime_error("dereference of unbound Handle");
	}
	
}

template <typename T>
inline T * Handle<T>::operator ->()
{
	if (m_pPtr!=nullptr)
	{
		return m_pPtr;
	}
	else
	{
		throw std::runtime_error("dereference of unbound Handle");
	}
}
	
template <typename T>
inline T & Handle<T>::operator *() const
{
	if (m_pPtr!=nullptr)
	{
		return *m_pPtr;
	}
	else
	{
		throw std::runtime_error("dereference of unbound Handle");
	}
}

template <typename T>
inline T * Handle<T>::operator ->() const
{
	if (m_pPtr!=nullptr)
	{
		return m_pPtr;
	}
	else
	{
		throw std::runtime_error("dereference of unbound Handle");
	}
}

main函数:

int*p = new int(100);

	Handle<int> pInt(p);

	Handle<int> pInt2 = Handle<int>(pInt);

	Handle<int> pInt3 = pInt2;

	try
	{
		cout << *pInt << "\t" << *pInt2 << "\t" << *pInt3 << endl;
	}
	catch (runtime_error e)
	{
		cerr<<e.what()<<endl;
	}

	try
	{
		*pInt3 = 200;
		cout << *pInt << "\t" << *pInt2 << "\t" << *pInt3 << endl;
	}
	catch (runtime_error e)
	{
		cerr << e.what() << endl;
	}

	int i = 0;
	try
	{
		pInt.~Handle();
		cout << ++i << "\t" << *pInt << "\t" << *pInt2 << "\t" << *pInt3 << endl;
		
		pInt.~Handle();
		cout << ++i << "\t" << *pInt << "\t" << *pInt2 << "\t" << *pInt3 << endl;
	}
	catch (runtime_error e)
	{
		cerr << e.what() << endl;
	}

	try
	{
		

		pInt.~Handle();
		cout << ++i<< "\t" << *pInt << "\t" << *pInt2 << "\t" << *pInt3 << ends; /*执行了前面的++操作,但是出现异常,异常销毁只会析构和处理变量,不会回滚操作*/
	}
	catch (runtime_error e)
	{
		cerr << i << "\t"<< e.what() << endl;
	}


程序结果:

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。