一直在使用C++11,某日被问到C++ 11 有哪些新特性时,茫然了,特做补充总结
来源于 C++ Primer Plus(第6版)中文版
1. auto关键字
要求显示初始化,让编译器能够将变量的类型设置为初始值的类型
auto maton=112;//maton is type int
auto pt=&maton; //pt is type int *
double fm(double ,int );
auto pf=fm; //pf is type double(*)(double,int)
//关键字简化模板声明
//如果il是一个std::initalizer_list <double>对象,则可使用如下表达式
for(std::initializer_list<double>::iterator p=il.begin();p!=il.end();p++)
//替换为如下
for(auto p=il.begin();p!=il.end();p++)
2. decltype关键字
关键字字decltype将变量的类型申明为表达式指定类型
decltype (x) y;
double x;
int n;
decltype(x*n) q;//q same type as x*n, i.e., double
decltype(&x) pd;//pd same type ad &x.,i.e.double*
//定义模板是很有用,因为只有模板实例化时才能却定类型
template<typename T,typename U>
void ef(T t,U u)
{
decltype(T*U) tu;
}
3. 返回类型后置
在函数名和参数列表后面 指定返回类型
double f1(double,int );//traditional syntax
auto f2(double ,int )->double; //new syntax, return type is double
4. 模板别名: using=
//以前C++ 提供typedef:
typedef std::vector<std::string>::iterator itType;
//C++ 11 提供另一种创建别名的语法
using itType =std::vector<std::string>::iterator;
//新语法的优点,在于可以用于模板部分具体化,但typedef不能
5. nullptr
空指针是不会指向有效数据的 指针。以前,C++在源代码中使用0表示这种指针,但内部表示可能不同。这带来一些问题,因为这使得0即可表示指针常量,又可表示整型常量。so C++新增了关键字nullptr,用来表示空指针,因此nullptr==0 为true,但使用nullptr而不是0 提供了更高的类型安全。
例如:可将0传递给接受int参数的函数,但如果您将nullptr传递给这样的函数,编译器会对此视为错误。因此处于清晰和安全考虑,请使用nullptr
6. 智能指针
如果在程序中使用new从堆(自有存储区)分配内存,等到不需要时,应使用delete将其释放。C++引入了智能指针auto_ptr,以帮助自动完成这个过程。随后的编程体验表明,需要有更精致的机制。基于程序员的编程体验和boost库提供的解决方案,C++摒弃了auto_ptr,并新增了三种智能指针:unique_ptr、shared_ptr和weak_ptr。
7. 作用域内枚举
传统的C++枚举提供了一种穿件名称常量的方式,但器类型检查相当低级。另外枚举名的作用域为枚举定义所属作用域,这意味着,如果在同意作用域内定义两个枚举,他们的枚举成员不能同名。最后枚举可能不是可完全移植的,因为不同的实现可能选择不同的底层类型。为了解决这一问题,C++新增了一种枚举。这种枚举使用class和struct定义:
num Old1{yes,no,maybe};
enum class New1 {never,sometimes,often,always};
enum struct New2 {never,lever,sever};
新枚举要求进行显示定义,以免发生名称冲突。因此,引用特定枚举时,需要使用New1::never 和 New2::never等。
8. 对类的修改
为了简化和扩展类设计,C++11做了多项改进。这包括允许构造函数被集成和彼此调用、更佳的方法访问控制方式及移动构造函数和移动赋值运算符
- 显示转换运算符
C++ 很早就支持对象自动转换,但随着编程经验的积累,程序员逐渐认识到,自动类型转换可能导致意外转换的问题。为了将诶绝这种问题,C++引入关键字 explicit,以禁止单参数构造函数导致的自动转换:
class Plebe
{
Plebe(int);//automatic int -to -plebe conversion
explicit Plebe(double);//requires explicit use
};
Plebe a,b;
a=5;//implicit conversion,call Plebe(5)
b=0.5; //not allowed
b=Plebe(0.5);//explicit conversion
C++ 1 1扩展了explicit 的这种用法,使得可对转换函数做类似的处理
class Plebe
{
...
//conversion functions
operator int () const;
explicit operator double () const;
......
};
.....
plebe a,b;
int n=a;
double x=b;//not allowed
x=double(b)//explicit conversion allowed
- 类内成员初始化
class Session
{
int mem1 = 10; //in-class initialization
double mem2{1996.54};
short mem3;
public:
Session(){}
Session(short s):mem3(3) {}
Session(int n ,double d,short s):mem1(n),mem2(d),mem3(s){}
.......
}
9. 模板和STL方面修改
- 基于范围的for循环
对于内置数组以及包含方法begin()和end()的类(如std::string)和STL容器,基于范围的for循环可简化编写循环的工作,这种循环对数组或容器中的每个元素执行指定操作:
double prices[5]={4.99,10.99,6.87,7.99,8.49};
for (auto x :prices)
cout<< x <<endl;
如果要在循环中修改数组或者容器的没个元素,可以使用引用类型
std::vector<int > vi(6);
for (auto &x :vi)
x=std::rand();
-
新的STL容器
C++ 11 新增了容器forward_list、unordered_map、unordered_multimap、unordered_set和unordered_multiset。 -
新的STL方法
C++ 11新增了STL方法cbegin()和cend() 。与begin()和end()一样,也是返回一个迭代器指向容器的第一个元素和最后一个元素的后面,因此可以用于指定包含全部元素的区间。另外这些新方法将元素视为const。 -
valarray升级
模板valarry独立与STL开发的,其最初的设计导致无法将基于范围的STL算法用于vslarry对象,。C++添加了两个函数(begin()和end()),他们都接受valarry作为参数,并返回迭代器,这些迭代器分别指向valarry对象的第一个元素和最后一个元素后面, -
摒弃export
c++98 新增了关键字export,旨在提供一种途径,让程序员能够将模板定义放在接口文件和实现文件中,其中前者包含原型和模板申明,而后者包含模板函数的方法和定义。实践证明这不现实,因此C++ 11终止了这种用法,但扔保留关键字export 供以后使用。 -
尖括号
为了避免与运算符>> 混淆,C++要求在申明嵌套模板是使用空格将尖括号分开:
std::vector<std::list > v1;//
C++ 11 中不在这样要求
std::vector<std::list > v1;// >>ok in C++11