c++ 11新特性之语法

1.auto
在C++中,可以使用auto来根据变量初始化表达式类型推导变量的实际类型,简化程序的书写

auto i = 1;//i -> int 
auto array = new auto(5);//array -> int *
auto s = "abc";
//c++ 03
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
	std::cout << *it << std::endl;
	}
//c++ 11
for (auto it = vec.begin(); it != vec.end(); it++) {
	std::cout << *it << std::endl;
	}

注意:
auto 不能用于函数传参,因此下面的做法是无法通过编译的(考虑重载的问题,我们应该使用模板);
auto 不能用于推导数组类型

2.decltype
 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了)。
为了满足这一需求,C++11新标准引入了decltype类型说明符,它的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

int i;
double t;
struct A { double x; };
const A* a = new A();
decltype(a) x1;  //x1 是 A*
decltype(i) x2;  //x2 是 int
decltype(a -> x) x3;  // x3 是 double

3.nullptr
空指针标识符nullptr是一个表示空指针的标识,他不是一个整数,这是与我们常用的NULL宏的区别。NULL只是一个定义为常整数0的宏,而nullptr是C++11的一个关键字,一个內建的标识符。

void fun(int a)
{
    cout << "call function: [int]\n" << endl;
}

void fun(int *a)
{
    cout << "call function: [int*]\n" << endl;
}

int main()
{
    //C++11
    fun(NULL);   //call function: [int]
    fun(nullptr);  //call function: [int*]

    int* p = NULL;
    fun(p);  //call function: [int*]

    return 0;
}

4.lambda表达式
Lambda 表达式,实际上就是提供了一个类似匿名函数的特性,而匿名函数则是在需要一个函数,但是又不想费力去命名一个函数的情况下去使用的。

Lambda 表达式的基本语法如下:

[ caputrue ] ( params ) opt -> ret { body; };
  1. capture是捕获列表;
  2. params是参数表;(选填)
  3. opt是函数选项;可以填mutable,exception,attribute(选填)
    mutable说明lambda表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获的对象的non-const方法。
    exception说明lambda表达式是否抛出异常以及何种异常。
    attribute用来声明属性。
  4. ret是返回值类型(拖尾返回类型)。(选填)
  5. body是函数体。
class A
{
 public:
     int i_ = 0;

     void func(int x,int y){
         auto x1 = [] { return i_; };                   //error,没有捕获外部变量
         auto x2 = [=] { return i_ + x + y; };          //OK
         auto x3 = [&] { return i_ + x + y; };        //OK
         auto x4 = [this] { return i_; };               //OK
         auto x5 = [this] { return i_ + x + y; };       //error,没有捕获x,y
         auto x6 = [this, x, y] { return i_ + x + y; };     //OK
         auto x7 = [this] { return i_++; };             //OK
};

int a=0 , b=1;
auto f1 = [] { return a; };                         //error,没有捕获外部变量    
auto f2 = [&] { return a++ };                      //OK
auto f3 = [=] { return a; };                        //OK
auto f4 = [=] {return a++; };                       //error,a是以复制方式捕获的,无法修改
auto f5 = [a] { return a+b; };                      //error,没有捕获变量b
auto f6 = [a, &b] { return a + (b++); };                //OK
auto f7 = [=, &b] { return a + (b++); };                //OK

注意:
[a,&b] 其中 a 以复制捕获而 b 以引用捕获。
[this] 以引用捕获当前对象( *this )
[&] 以引用捕获所有用于 lambda 体内的自动变量,并以引用捕获当前对象,若存在
[=] 以复制捕获所有用于 lambda 体内的自动变量,并以引用捕获当前对象,若存在
[] 不捕获,大部分情况下不捕获就可以了

5.for循环
C++11 引入了基于范围的迭代写法,我们拥有了能够写出像 Python 一样简洁的循环语句。

// & 启用了引用
for(auto &i : arr) {    
    std::cout << i << std::endl;
}

6.初始化列表
C++11扩大了用初始化列表的使用范围,让其适用于所有的内置类型和自定义类型,而且使用时,=可以不写

// 内置类型
int x1 = {10};
int x2{10}
// 数组
int arr1[5] {1,2,3,4,5}
int arr2[]{1,2,3,4,5};
// 标准容器
vector<int> v{1,2,3}
map<int,int> m{{1,1},{2,2}}
// 自定义类型
class Point
{
int x;
int y;
}
Power p{1,2};

7.override(更加安全直观)

class base {
public:
	virtual void fun1(int);
	virtual void fun2() const;
	void fun3(int);
};

class son :public base {
	//c++ 03 存在隐患
	/*
	void fun1(float);  //不小心写错了参数,ok 编译通过,create a new func
	void fun2();       //不小心少写了const,ok 编译通过,create a new func
	void fun3();
	*/

	// but in c++ 11 更安全清晰
	void fun1(float) override; //编译Error: no func to override
	void fun2() override;      //编译Error: no func to override
	void fun3() override;      //编译Error: no func to override			
};

8.final
作用于类上,表示类不可被继承。

class Base final{

}

作用于虚函数上,表示该虚函数不可被重写。

class Base{
    virtual void f() final;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值