C++11:右值引用-移动语义

先来看这样一个例子:

class TestClass
{
public:
	TestClass()
	{
		d = new int[10];
	}
	TestClass(const TestClass &t)
	{
		d = new int[10];
	}
	~TestClass()
	{
		delete d;
		d = nullptr;
	}

private:
	int *d;
};

TestClass get_test_class()
{
	TestClass t;
	return t;
}

void run_test()
{
	TestClass t2 = get_test_class();
}

在这个例子中,首先get_test_class函数中的TestClass t语句进行了一次构造,并且开辟了heap内存,接着在值传回来时,其拷贝构造函数为了实现深拷贝,又开辟了一次heap内存。也就是说,这样为了拿到一个对象,总共有两次heap内存的开辟。并且其中一次是临时变量,其生命期结束后就会被销毁,看起来似乎造成了性能的浪费。

Read more

C++11:POD类型

POD概念在C++中是一个非常重要的概念,是Plain Old Data的缩写.

POD类型是指该类型是一个平凡而普通的类型,由以下两部分概念构成:

平凡的(trivial)

1.拥有平凡的默认构造函数(trivial constructor)和析构函数(trivial destructor).

平凡的意思是什么都不干。通常来说,不定义类的构造函数,编译器会生成一个默认构造函数。而一旦我们定义了构造函数,即使这个构造函数无参数,没任何代码,那么也不再是平凡的(也可以通过C++11的新特性=default让其恢复平凡).

2.拥有平凡的拷贝构造函数(trivial copy constructor)和移动构造函数(trivial move constructor).

3.拥有平凡的拷贝赋值运算符(trivial assignment operator)和移动赋值运算符(trivial move operator).

4.不能包含虚函数以及虚基类.

标准布局

1.所有非静态成员有相同的访问权限.

Read more

C++11:变长模板

C++11中添加了变长模板的支持,模板参数已经可以像printf函数那样接受不受限个参数个数,我们先来看个简单的样例:

void func()
{

}

template<class A,class...B>
void func(A argHead, B...argTail)
{
	func(argTail...);
}

int test_func()
{
	func(1, 2, 3, 4, 6);
	return 0;
}

在func有两个版本,第一个为无参数传递的特化版本,另外一个就是主体变长模板参数版本.
在func的class…B表示B这个参数是可变长的,称之为:模板参数包(template parameter pack)。

Read more

C++:一些约束

利用模板可以制作一些在编译期就能侦察到的违反你理想中的规定的情况,所谓约束.

第一个约束用来要求class D一定继承与B:

template<typename D,typename B>
struct must_have_base
{
	~mush_have_base()
	{
		void(*p)(D*, B*) = constraint;
	}

private:
	static void constraint(D* d, B* b)
	{
		b = d;
	}
};

constraint是一个静态函数,并且在must_have_base中声明了一个其函数指针,于是迫使编译器在编译期就要做出评估操作.

另外一个约束要求一个类型可以按照下标形式访问:

template <typename T>
struct must_be_subscriptable
{
	~must_be_subscriptable()
	{
		void(*p)(T) = constraint;
	}

private:
	static void constraint(T const &T_is_not_subscriptable)
	{
		sizeof(T_is_not_subscriptable[0]);
	}
};

还有一个约束可看这里:must_be_subscriptable_as_decayable_pointer

Read more

C++11:lambda函数

C++11的一个重大特性就是lambda函数的加入,匿名函数的加入使得C++程序员更加能够专注逻辑的本身,这也是在函数式语言日渐兴起的一种跟进.

在看本文前,我们假设你已经了解过C++11的追踪返回类型特性.

先看一个例子:

void func()
{
	int a = 3;
	int b = 2;

	auto total = [](int x, int y) ->int
	{ 
		return x + y; 
	};

	int result = total(a, b);
}

在这个例子中,我们定义了一个lambda函数,她接受两个int参数,返回这两个参数的和。初次一看可能觉得语法怪异,现在我们来讲述一下其语法:

[capture](parameters) mutable->return-type
{
	statement
}

Read more

C++11:自动类型推导-追踪返回类型

这是C++11 自动类型推导的第三篇,在之前的文章里,介绍了autodecltype.

这一篇来讲述如何通过auto和decltype来提高泛型编程能力,先看一个sample:

template<typename T1,typename T2>
auto test(T1 &t1, T2 &t2) ->decltype(t1 * t2)
{
	return t1 * t2;
}

函数的返回类型被定义成了auto,由其return的类型决定,为了支持这一个功能,需要添加使用C++11的新的“追踪返回类型”的语法,在这里为->decltype(t1 * t2).

Read more

return top