C++11_新语法
版权声明:本文为博主原创文章,未经博主允许不得转载。
本节主要介绍C++的新特性,对于C++的基础语法不再讲解.由于编译器的不同.在某些地方可能有些差异,但是无太大影响.
讲解本节知识之前先确认你的C++支持度[__cplusplus]
#include <iostream> int main(int argc, const char * argv[]) { std::cout<<__cplusplus<<std::endl; return 0; }
会看到这样,说明支持C++11
主要介绍如下:
新特性 1 模板套模板
新特性 2 空指针
新特性 3 新auto
新特性 4 新初始化
新特性 5 initializer_list<>
新特性 6 新for循环
新特性 7 =default与=delete
新特性 8 Alias Template(template typedef)
新特性 9 Type Alias
新特性 10 noexcept,override,final关键字
新特性 11 decltype
新特性 1 模板套模板
在旧版本的C++中模板套用模板可能要加空格,像这样
vector<list<int> > //旧板中需要加空格 vector<list<int>> //新模板中不需要加
新特性 2 空指针
新规定中nullptr可以代替0和NULL(0指针)
void f(int) { cout << "f(int) be called" << endl; } void f(void*) { cout << "f(void*) be called" << endl; } f(0); //calls f(int) f(NULL); //calls f(int) if NULL is 0 f(nullptr); //calls f(void*)
新特性 3 新auto
1.自动识别类型(编译器的实参推倒)
auto i = 42; //自动识别 i为 int auto d = func(); //自动识别d为函数返回值
2.如果初始化表达式是引用,则去除引用语义.如果auto关键字带上&号,则不去除const语意
int a = 10; int &b = a; auto c = b;//c的类型为int而非int&(去除引用) auto &d = b;//此时c的类型才为int&
3.如果初始化表达式为const或volatile,则除去const/volatile语义.
const int ci=i,&cr=i; auto a=ci; //a为int(忽略顶层const) auto b=cr; //b为int(忽略顶层const,cr是引用) auto c=&i; //c为int * auto d=&ci; //d是pointer to const int(&ci为底层const
4.初始化表达式为数组时,auto关键字推导类型为指针.
int main() { int array[3]{ 1, 2, 3 }; auto array_b = array; std::cout << typeid(array_b).name() << std::endl; return 0; }
输出结果Pi(int*)
注意事项
1.auto声明的变量必须要初始化,否则编译器不能判断变量的类型.
2.auto不能被声明为返回值(但可以与decltype结合使用做返回值的站位下文有),auto不能作为形参,auto不能被修饰为模板参数
新特性 4 新初始化
C++11之前的初始化
Rect r1 = {3,7,20,25};//大括号 Rect r2(3,7,20,25) ;//小括号 int arry[3] = {1,2,3};//[]
C++11之后一切的初始化都可以用 {} 代替
int value[] {1,2,3}; vector<int> v {1,2,3}; complex<double> c {1,2,3};
新初始化的优点
int i; //初始值不知道 int i{}; //初始值是0 int * p;//初始值不知道 int * p{}; //初始值是nullptr //{} 不允许窄化转换 int x1(5.3);它会被初始化为5 int x2{5.3};它会报错
新特性 5 initializer_list<>
一包东西,但是类型得是相同的,实现C++源码的重要语法,知道怎么用就可以.传递过程不需要我们担心,编译器会自动处理
int main(int argc, const char * argv[]) { std::initializer_list<int> t1 {1,2,3,4}; std::cout<<max(t1)<<std::endl;//新的max() 传参采用 initializer_list 不在受限于参数个数 return 0; }
输出结果
新特性 6 新for循环
新的for循环采用for(del声明 : coll容器),与旧for()不冲突
#include <iostream> #include <vector> int main() { std::vector<int> v1 {1,2,3,4,5}; for (auto i: v1) { //此时的auto变量i是 pass by value 不能改变容器中的成员如果想改变其成员,需要pass by reference std::cout<< i <<std::endl; } return 0; }
输出结果
pass by reference写法
int main() { std::vector<int> v1 {1,2,3,4,5}; for (auto& i: v1) { i *= 3;//此时传递的是引用,可以改变vector中的成员 } return 0; }
新特性 7 =default与=delete
class Zoo//delete删掉编译器给的 default要编译器给的即使定义了也要让编译器给出 { public: Zoo(int i1,int i2) : d1(i1),d2(i2) {} Zoo(const Zoo&) = delete;//拷贝构造函数 Zoo(Zoo&&) = default;//右值引用 Move() Zoo & operator = (const Zoo&) = default; Zoo operator = (const Zoo&&) = delete; virtual ~Zoo(); private: int d1,d2; };
a. =default用于普通函数无意义(构造函数可以共存)
b. =delete用于普通函数可以取代于virtual function = 0
c. BIG-Three 默认构造函数 默认拷贝构造函数 默认析够函数 他们三个函数的作用是给编译器防止一个幕后藏身的地方 如父类的构造函数调用过程.
类中有指针成员,需要重写BIG-Three没有则不用
d. 类中讲拷贝构造与构造函数声明成private 如果你的类继承自noncopyable 那么你的类也不能被拷贝
简单实现一下noncopyable
class noncopyable { protected: noncopyable (void) {} ~noncopyable (void) { } private: noncopyable (const noncopyable&); const noncopyable& operator= (const noncopyable&); };
新特性 8 Alias Template(template typedef)
功能相当于取别名
template<typename T> using vec = std::vector<T,std::allocator<T>>; int main() { vec<int> v1 {1,2,3,4}; for(auto i: v1) { std::cout<< i <<std::endl; } return 0; }
新特性 9 Type Alias
类似于typedef,重新命名
typedef void (*func) (int, int); using func = void(*) (int,int);//这两个函数意义相同 但是感觉using更容易让人理解
template <typename T> struct Container { using value_type = T; // 相同于 typedef T value_type; };
新特性 10 noexcept,override,final关键字
//noexcept 保证函数不会丢出异常 void foo() noexcept; //== void foo() noexcept(true) 括号内处条件 在完成什么条件下不会抛出异常 void swap(string & x ,string & y) noexcept(noexcept(x.swap(y))) { x.swap(y); } class MyString { private: char * _data; size_t _len; public: //move constructor move语法必须用noexcept 尤其在vecotr上 不然不让编译 (voctor 是按传进参数个数成长 很容易在申请内存上出错) move意义上当于 by reference MyString(MyString&& str)noexcept : _data(str._data), _len(str._len){} MyString& operator= (MyString&&str) noexcept {return *this;} };
//override 运用在虚函数上 自动识别是否是虚函数 struct Base { virtual void vfunc(float){} }; struct Drivedl:Base { virtual void vfunc(float) override {}//自动识别该函数是否是基类中的虚函数 如果不是报错 };
//final 继承树下的最后一个 (没有人可以在继承它) struct Base1 final{};//1.作用于类,该类不可被继承 struct Base2 { virtual void f() final;//2.作用于函数 该虚函数不可以被重写 };
新特性 11 decltype
相当于type of (识别类型),然编译器去识别type,不能识别重载的函数
1.基本使用方法
int main() { auto num = 1; //num 是int类型 decltype(num) num2 = num; //num2 也是int类型 return 0; }
2..声明返回值类型
//判断两个参数相加的返回值类型 template<typename T1,typename T2> auto add(T1 x, T2 y) -> decltype(x+y);
3. 做参数
class Person { public: Person(){}; ~Person(){}; public: int m_age = 0; std::string lastname = ""; std::string firstname = ""; }; auto cmp = [](const Person& p1,const Person& p2)//lambda { return p1.lastname<p2.lastname|| (p1.lastname == p2.lastname && p1.firstname< p2.firstname); }; int main() { std::set<Person,decltype(cmp)> coll(cmp); Person * p1 = new Person; p1->lastname = "a"; Person * p2 = new Person; p2->lastname = "b"; Person * p3 = new Person; p3->lastname = "c"; coll.insert(*p3); coll.insert(*p1); coll.insert(*p2); for (auto i: coll) { std::cout<<i.lastname<<std::endl; } return 0; }
输出结果
参照<<侯捷 C++新标准 C++11>>
如有不对请指正.