C++11中一些常见的特性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wk_bjut_edu_cn/article/details/84143939

C++11标准由国际标准化组织(ISO)和国际电工委员会(IEC)旗下的C++标准委员会(ISO/IEC JTC1/SC22/WG21)于2011年8月12日公布 [2]  ,并于2011年9月出版。2012年2月28日的国际标准草案(N3376)是最接近于C++11标准的草案(仅编辑上的修正)。此次标准为C++98发布后13年来第一次重大修正。

一、auto类型说明符

auto类型说明符能够让编译器替我们去分析表达式所属的类型。所以,auto定义的变量必须有初始值。

需要注意的是,auto一般会忽略顶层const,同时底层const则会保留下来。

#include <iostream>
using namespace std;
int main(void)
{
	int i = 5, m = 3;
	const int j = i, &k = j;
	auto b = j;//b是一个整数(j的顶层const特性被忽略调了)
	b = 6;//可以对b进行修改
	auto c = k;//c是一个整数(k是j的别名,j本身是一个顶层const)
	c = 8;//可以对c进行修改
	auto d = &i;//d是一个整型指针
	auto e = &j;//e是一个指向整数常量的指针(属于底层const)
	*e = 4;//错误,e是指向整数常量的指针
	system("pause");
	return 0;
}

二、decltype类型指示符

有时会遇到这种情况:希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量。decltype的作用就是选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

#include <iostream>
using namespace std;
int fun()
{
	int num = 6;
	return num;
}
int main(void)
{
	int i = 6;
	decltype(fun()) result = i; //result的类型就是函数fun()的返回类型
	cout << result << endl;
	system("pause");
	return 0;
}

其次,decltype处理顶层const和引用的方式与auto有区别。如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内)

#include <iostream>
using namespace std;
int main(void)
{
	const int i = 3, &j = i;
	decltype(i) a = 4;//a的类型是const int
	//a = 5;//错误
	decltype(j) b = a;//b的类型是const int&,b绑定到变量x
	decltype(j) c;//错误:c是一个引用,必须初始化
	system("pause");
	return 0;
}

三、范围for语句

C++11 新标准引入了一种简单的for语句,这种语句可以遍历容器或其它序列的元素。

#include <iostream>
#include<vector>
using namespace std;
int main(void)
{
	vector<int> v = { 1,2,3,4,5 };
	for (auto i : v)
		cout << i << " ";
	return 0;
}

四、匿名函数lambda

我们可以向一个算法传递任何类别的可调用对象。对于一个对象或一个表达式,如果可以对其使用调用运算符,则称它为可调用的。也就是说,如果e是一个可调用的表达式,则可以编写e(args)。

#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool cmp(int a, int b)
{
	return  a < b;
}
int main(void)
{
	vector<int> v = { 1,3,5,4,6 };
	for (auto i : v)
		cout << i << " ";
	cout << endl;
	sort(v.begin(), v.end(), [](int a, int b) -> bool { return a < b; });   // Lambda表达式
	for (auto i : v)
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

五、尾置返回类型

尾置返回类型是C++11新标准中简化声明函数的方法。常规情况下,如果我们想要定义一个返回数组指针的函数,是比较麻烦的,但通过使用尾置返回类型,就变得容易许多。

(1)常规方法:声明一个返回数组长度为10的整形数组

int (*func(int i))[10];

(2)使用typedefusing关键字

typedef int arrT[10];   
//等价于 using arrT = int[10];

arrT* func(int i);     //声明func函数

(3)使用尾置返回类型

auto func(int) -> int(*)[10];  //声明Func函数

此外,我们还可以在模板中使用尾置返回类型

//示例中模板接受一对迭代器和返回序列中的一个解引用
template <typename It>
auto fcn(It beg, It end) -> decltype(*beg)
{
	return  *beg;		//返回序列中一个元素的引用
}

六、nullptr

#include <iostream>
using namespace std;
void func(void* t)
{
    cout << "func1" << endl;
}
void func(int i)
{
    cout << "func2" << endl;
}
int main()
{
    func(NULL);
    func(nullptr);
    system("pause");
    return 0;
}

看起来NULL和nullptr都是代表空指针,但是NULL在重载函数的时候却匹配到了参数为int的那个版本。 
这是因为在C++中,NULL的定义一般是这样的:

#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif // __cplusplus

可以看到,其实NULL在C++中就是代表着0,这是因为在C++中void* 类型是不允许隐式转换成其他类型的,所以C++中用0来代表空指针,但是在重载整形的情况下,会出现上述的问题。所以,C++11加入了nullptr,可以保证在任何情况下都代表空指针,而不会出现上述的情况,因此,以后应该使用nullptr。

七、override(覆盖)

函数重写是指子类重新定义基类的虚函数。特征是:

如果派生类在虚函数声明时使用了override描述符,那么该函数必须重载其基类中的同名函数,否则代码将无法通过编译。

(1)不在同一个作用域(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有 virtual 关键字,不能有 static 。
(5)返回值相同,否则报错;
(6)重写函数的访问修饰符可以不同;

#include <iostream>
using namespace std;
struct Base
{
	virtual void wangkai();
	virtual void nangua();
	virtual void liyuan(int g) = 0;
	virtual void pangge() const;
	void huowei();
};
void Base::wangkai()
{
	cout << "wangkai" << endl;
}
void Base::nangua()
{
	cout << "nangua" << endl;
}
void Base::pangge() const
{
	cout << "pangge" << endl;
}
void Base::huowei()
{
	cout << "huowei" << endl;
}

struct Derived:public Base
{
	virtual void wangkai() override;
	void nanguaN();
	virtual void liyuan(int g) override;
	virtual void pangge() const override;
	//void huowei();//非虚函数不可以使用override
};
void Derived::wangkai()
{
	cout << "wangkai666" << endl;
}
void Derived::liyuan(int g)
{
	cout << "liyuan" << endl;
}
void Derived::nanguaN()
{
	cout << "nanguaN" << endl;
}
void Derived::pangge() const
{
	cout << "pangge" << endl;
}
/*
void Derived::huowei()
{
	cout << "huowei666" << endl;
}
*/
int main(void)
{
	Derived d1;
	d1.nanguaN();
	d1.nangua();
	d1.wangkai();
	d1.huowei();
	system("pause");
	return 0;
}

八、shared_ptr类

在C++中,动态内存的管理是通过一对运算符来完成的,即new和delete。动态内存的使用容易出问题,比如忘记释放内存、释放正在使用的指针等。新的标准库提供了两种智能指针类型来管理动态对象。它们能够自动释放所指向的对象。shared_ptr允许多个指针指向同一个对象;unique_ptr则”独占“所指的对象。它们都定义在memory头文件中。
参照另一篇博客智能指针

猜你喜欢

转载自blog.csdn.net/wk_bjut_edu_cn/article/details/84143939