C++11实现模板手柄:委托构造函数、defaultkeyword分析

C++11。使用委托构造函数。和高速变量初始化,defaultkeyword重新声明默认构造函数,回答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声明。可是假设考虑和委派构造函数一起使用的话,则会有例如以下的错误:

Handle() = default:Handle(p,new std::size_t(1)){};
1>d:\cpp_2013\testqueue_16th_2\testqueue_16th_2\handle.hpp(7): error C2143: 语法错误 : 缺少“;”(在“:”的前面)

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

原因在:一旦使用defaultkeyword去重定义默认的构造函数使其回复至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;
	}

委派构造函数的使用在于内部能定义一个完整版本号的构造函数,然后在类对象未完毕初始化时调用该构造函数,先在当前地址完毕构造。这个思维应该是曾经this为很量时代(事实上我没用过很量指针形式的this)的使用方法,后来新标准定义this仅仅能为const类型,融合当前代码时长出现大量的构造函数。思考出的解决方式,不算是语法上的突破或革新。

程序结果:

源代码

版权声明:本文博主原创文章。博客,未经同意不得转载。

时间: 2024-12-20 01:11:19

C++11实现模板手柄:委托构造函数、defaultkeyword分析的相关文章

【C++ Primer 第七章】 构造函数再探、委托构造函数

构造函数初始值列表 1.  构造函数的初始值有时必不可少 • 有时我们可以忽略数据成员初始化和赋值之间的差异,但并非总能这样.如果成员时const或者是引用的话,必须将其初始化.类似的,当成员属于某种类类型且该类没有定义默认构造函数时,也必须将这个成员初始化. 例如: 1 class ConstRef 2 { 3 public: 4 ConstRef(int ii); 5 private: 6 int i; 7 const int ci; 8 int &ri; 9 }; 和其他常量对象或者引用一

编译器对C++ 11变参模板(Variadic Template)的函数包扩展实现的差异

编译器对C++ 11变参模板(Variadic Template)的函数包扩展实现的差异 题目挺绕口的.C++ 11的好东西不算太多,但变参模板(Variadic Template)肯定是其中耀眼的一颗明星,在C++设计新思维中,你可以看到很多模版的代码为了支持不确定的参数个数,而要重载1个参数到N个模板参数的N个函数.虽然种代码一般也是用会用宏和脚步辅助生成.但我想也没有人愿意看到几千行这种单调的函数.通过这个东东,模板的威力可以爆发. 目前的最新的编译器基本都已经支持Variadic Tem

C++学习笔记18,C++11中的初始化列表构造函数(二)

C++11中的初始化列表构造函数(Initialize_list Constructors)是将std::initializer_list<T>作为第一个参数的构造函数,并且没有任何其他参数(或者其他参数具有默认值).例如: #include <iostream> #include <initializer_list>//必须包含该头文件 #include <vector> using namespace std; class A { private: ve

风险评估DNV GL AS Phast v7.11.33.0/海洋结构物强度分析DNV sesam suite 2013海洋结构物强度分析

风险评估DNV GL AS Phast v7.11.33.0/海洋结构物强度分析DNV sesam suite 2013海洋结构物强度分析DNV Phast Risk v6.7-ISO 1DVDDNV Phast v6.7-ISO 1DVD 最新6.7版本 全功能无限制DNV sesam suite 2013 Full 1CD包含新的 DeepC .GeniE和HydroD模块.DNV sesam Genie 2013 Full 1CD(用于评估无航速浮体流体动力性能的计算软件)DNV Soft

2017年11月11日软考网络工程师案例分析真题及答案解析

[徐朋出品,必属精品]软考徐朋老师全网最先发布2017年11月11日软考网络工程师案例分析真题及答案解析,是全网最清新版本.详细讲解了2017年11月11日最新开考的软考网络工程师案例分析真题及答案.课件中对每一道真题都进行了详细的解析讲解,考后几周是学员记忆答案的最关键时间点,第一时间发布真题及答案帮助广大考生准确评估自己的考试结果及对未来参加考试的学员展示最新的考试趋势等.下载地址:http://down.51cto.com/data/2340424

2017年11月11日软考网络规划设计师案例分析真题及答案解析

[徐朋出品,必属精品]软考徐朋老师全网最先发布2017年11月11日软考网络规划设计师案例分析真题及答案解析,是全网最清新版本.详细讲解了2017年11月11日最新开考的软考网络规划设计师案例分析真题及答案.课件中对每一道真题都进行了详细的解析讲解,考后几周是学员记忆答案的最关键时间点,第一时间发布真题及答案帮助广大考生准确评估自己的考试结果及对未来参加考试的学员展示最新的考试趋势等.下载地址:http://down.51cto.com/data/2340406

C++11的模板新特性-变长参数的模板

这个特性很赞,直接给例子吧,假如我要设计一个类,CachedFetcher内部可能使用std::map也可能使用std::unordered_map,也可能是其它的map,怎么设计呢?没有C++11变长模板之前这很费劲.. 因为map的模板参数可不是只有key,value两个啊,还有一些有默认参数的template参数... ? ? template<typename _Key, typename _Value, template<class _Kty, class _Ty, typename

C++11变参模板

在C++11中出现的变参模板,可以让我们不需关心函数调用的参数多少,类似实现C中的printf函数那样. 变参依赖于C++强大的模板 可以这样声明 template<class T1,class... Args>   //   Args就是一种类型参数包,在定义的函数中需要递归去解析 void MutiArg(const T1&t1,Args... args) { //  do something with t1对第一个调用参数进行操作 MutiArg(args...);  //对参数

c++11:模板

c++11中Universal Reference类型的模板参数的推导规则? universal refences 简单来说就是type&& + syntax + type deduction,即可以引用左值,也可以引用右值. template<typename T> void f(P); f(A); Effective Modern C++ 条款1 理解模板类型推断 C++11之经典书籍和网文推荐 原文地址:https://www.cnblogs.com/losophy/p/