C++11的一些特性

来源:互联网 发布:php if判断语句 编辑:程序博客网 时间:2024/06/06 17:18

1.断言是将一个需要为真的表达式放在语句中,在debug模式下检查一些逻辑错误的参数,C++中使用assert需要使用<assert.h>或者<cassert>头文件。有函数定义如下:

void  fun(int a[],int n){assert(n>0);//dosomething;}

这样就可以检查n<=0的情况,如果遇到这种情况,程序会调用abort()函数而终止。

C++11提供了static_assert断言,它的函数原型接受两个参数,一个是断言表达式,一个是警告信息,可以用字符串表示。

static_assert(sizeof(int)==8,”64-bitmachine should follow this”);int   main(){return  0;}

可见,static_assert()assert提供了更多的信息。另外,static_assert()用于在编译期做断言判断,而assert()用于在运行期间做断言判断。

2.__func__C++99标准中预定义的标识符,功能是返回所在函数的名字,C++11标准中,__func__可以用于结构体中,如:

#include <iostream>#include <cstdlib>using  namespace std;struct  Test{Test():name(__func__){}const  char *name;};int  main(){Test  t;cout<<t.name<<endl;return  0;}

3.委派构造函数

class  A{public:A(){init();}A(int i):x(i){init();}A(double d ):f(d){init();}private:void  init();int  x;double  f;};

上面的代码中,三个版本的构造函数都调用了init()函数,有没有办法简化这段代码呢?

可以使用委派构造函数:

class  A{public:A(){init();}A(int i):A(){x=i;}A(double d):A(){f=d;}private:void  init();int  x;double  f;};

4.初始化列表

#include <vector>#include <iostream>using  namespace std;int  main(){int  a[]={1,2,3};int  b[]{1,2,3};vector<int> c{1,3,5};return  0;}

C++11支持这样几种初始化的方式:

赋值符号 如int  a=1+2;

赋值符号加上初始化列表 int  a={1+2};

圆括号 int  a(1+2);

花括号加上初始化列表 int  a{1+2}

5.右尖括号的改进

template <class T>

classA

{};

vector<A<int>>v;//c++98编译失败,C++11编译成功

vector<A<int> > v;//C++98编译成功,C++11编译成功

6.auto类型推导

#include<iostream>using  namespace std;int main(){auto name=”world\n”;cout<<”hello ”<<name<<enld;return 0;}

auto会自动推导出name的类型为constchar *,然后在cout语句中输出

基于auto的上述特点,auto可以初始化复杂类型变量,可以支持泛型编程

7.for循环的改进

#include <isotream>using namespace std;void action(int &e){cout<<e<<endl;}int main(){int arr[3]={1,2,3};int *p=arr;for(;p<a+3;++p)cout<<*p<<endl;for_each(arr,arr+sizeof(arr)/sizeof(arr[0]),action);//for_eachfor(int &e:arr) //另外一种写法{cout<<e<<endl;}for( auto e:arr) //auto自动类型推导{cout<<e<<endl;}return 0;}

8.智能指针

C++使用的是auto_ptr,C++11中它被废弃了,取而代之的是unique_ptr,shared_ptrweak_ptr,

unique_ptr的缺点是必须独自占有内存,不能直接用=来进行赋值,而且使用move方法赋值之后,指针会失去所有权。

#include <iostream>#include <memory>using namespace std;int main(){unique_ptr<int >  p1(new int(1));unique_ptr<int> p2=p1; //编译错,不能直接赋值unique_ptr<int> p3=move(p1);cout<<*p3<<endl;cout<<*p1<<endl; //运行出错,p1的所有权已经交给了p3return 0;}

shared_ptr是表现的最像指针的智能指针。它使用引用计数来表示当前多少指针指向同一块内存,一个指针被释放,引用计数就会减少1,直到引用计数减少为0时,指针指向的内存才会真正的释放。

weak_ptr是作为shared_ptr的辅助,它本身不会引起引用计数的增加,它可以用来检验share_ptr的有效性。

#include <iostream>#include <memory>using  namespace std;void  check(weak_ptr<int> &p){shared_ptr<int>  t=p.lock();if(t!=nullptr)cout<<”ok”<<endl;elsecout<<”error”<<endl;}int  main(){shared_ptr<int>  p1(new int(1));shared_ptr<int>  p2=p1;weak_ptr<int> wp=p1;check(wp); //okp1.reset();check(wp); //okp2.reset();check(wp); return  0;}

9.空指针nullptr

C++98中,空指针NULL是一个宏,类似于#define NULL0的形式,所以NULL本质上是个整型。C++11提出了nullptr代替NULL作为空的指针常量。nullptr相对于NULL有什么优势,可以看下这个函数重载的例子。

void f(int i){}

void  f(char *c){}

f(NULL)将会调用f(int)的版本,因为NULL0

f(nullptr)将会调用f(char*c),因为nullptrnullptr_t类型的

nullptrnullptr_t的关系:nullptr_t是指针类型,nullptrnullptr_t类型的常量

nullptr_t的性质有:

nullptr_t类型数据可以隐式转换成任意一个指针类型

nullptr_t不能转换为非指针类型,

nullptr_t可以用于关系运算,但不能用于算术运算

#include <iostream>#include <typeinfo>using namespace std;int  main(){char*p=nullptr; //转换为指针类型int t=reinterpret_cast<int>(nullptr);//编译出错,nullptr_t类型不能转换为intnullptr_tptr;if(ptr==nullptr) //可以用于关系运算cout<<”nullptr”<<endl;nullptr+=1;//编译出错,不能用于算术运算return  0;}

10.lamda函数

#include <iostream>using namespace std;int  main(){int  a=1;int  b=2;auto  fun=[=]()->int{return a+b;};cout<<fun()<<endl;;return  0;}

auto  fun=[=]()->int{return a+b}定义了fun函数,它是lamda函数

lamda函数的定义方法如下:

[capture](parameter list) mutable ->return type {//do something;}

有关各个字段的含义这里不再赘述。

下面是lamdastl中应用的一个例子:

#include <iostream>#include <algorithm>#include <vector>using namespace std;inline  void cmp(int i){if(i>7)cout<<"larger  than  7"<<endl;}int  main(){int  a[10]={1,2,3,4,5,6,7,8,9,0};vector<int>  v(a,a+10);for(auto it=v.begin();it!=v.end();++it){if(*it>7)cout<<"largerthan 7"<<endl;}for_each(v.begin(),v.end(),cmp);for_each(v.begin(),v.end(),[=](int i){if(i>7)cout<<"largerthan 7"<<endl;});return  0;}

上面的代码遍历一个容器vector,使用了三种方法,一是利用迭代器,逐个判断,二是利用仿函数,三是利用了lamda函数。



0 0
原创粉丝点击