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)使用typedef或using关键字
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头文件中。
参照另一篇博客智能指针