c++ 关键字

mutable

是为了突破 const 的限制而设置的。可以用来修饰一个类的成员变量。被 mutable 修饰的变量,将永远处于可变的状态,即使是 const 函数中也可以改变这个变量的值。

explicit

跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式)

explicit可以防止隐式转换的发生,explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了

例如:一个类A的构造函数A(int i)就是,既可以用来作为构造器,又可以实现隐式转换A a=1;因为1可以通过构造函数A(int i)转换为一个类A的对象。(隐含的类型转换操作符)
但有时我们并不想让他进行隐式类型转换,这时C++的explicit关键字就起到作用了.

注意:当类的声明和定义分别在两个文件中时,explicit只能写在在声明中,不能写在定义中。

volatile

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统,硬件或者其他线程等。

 遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据(而不是寄存器),即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存

final

final用于修饰类,该类不能再被继承

inal用于修饰虚函数,表明子类不能重写该虚函数,为”终结虚函数“。

override

假如我们继承基类的虚函数,在重写虚函数时写错了,参数类型不对或个数不对,但是编译没问题,造成了对基类同名函数的隐藏,运行时候和设计的不一样,
override就是辅助检查是否正真重写了继承的虚函数,例如:

  struct B4{
    virtual void g(int) {}
  };
 
  struct D4 : B4{
    virtual void g(int) override {}    // OK
    virtual void g(double) override {} // Error
 };

default

我们知道,C++98和C++03编译器在类中会隐式地产生四个函数:默认构造函数、拷贝构造函数、析构函数和赋值运算符函数,它们被称为特殊成员函数。
在 C++11 中,被称为 “特殊成员函数” 的还有两个:移动构造函数 和 移动赋值运算符函数。如果用户申明了上面六种函数,编译器则不会隐式产生。
C++引入的default关键字,可显示地、强制地要求编译器为我们生成默认版本

  class DataOnly{
  public:
	DataOnly()=default;    							//default constructor
	~DataOnly()=default;              				//destructor

	DataOnly(const DataOnly& rhs)=default;    		//copy constructor
    DataOnly& operator=(const DataOnly & rhs)=default;  //copy assignment operator

    DataOnly(const DataOnly && rhs)=default;  		//C++11,move constructor
    DataOnly& operator=(DataOnly && rhs)=default;  	//C++11,move assignment operator
  };

上面的代码,就可以让编译器生成上面六个函数的默认版本。

delete

1、禁止编译器生成上面六种函数的默认版本。

  class DataOnly{
  public:
	DataOnly()=delete;	//default constructor
	~DataOnly()=delete;	//destructor

	DataOnly(const DataOnly& rhs)=delete;	//copy constructor
	DataOnly& operator=(const DataOnly & rhs)=delete;  //copy assignment operator

	DataOnly(const DataOnly && rhs)=delete;  //C++11,move constructor
	DataOnly& operator=(DataOnly && rhs)=delete;  	//C++11,move assignment operator
  };

2、C++11 中,delete 关键字可用于任何函数,不仅仅局限于类成员函数。在函数重载中,可用delete来滤掉一些函数的形参类型

  bool isLucky(int number);        // original function
  bool isLucky(char) = delete;     // reject chars
  bool isLucky(bool) = delete;     // reject bools
  bool isLucky(double) = delete;   // reject doubles and floats

3、在模板特例化中,也可以用 delete 来过滤一些特定的形参类型。

例如,Widget 类中声明了一个函数模板,当进行模板特化时,要求禁止参数为 void* 的函数调用。

  class Widget{
  public:
	template<typename T> void processPointer(T* ptr){}
  };
  template<> void Widget::processPointer<void>(void*)=delete;	//deleted function template

thread_local

....

decltype

decltype 关键字是为了解决 auto 关键字只能对变量进行类型推导的缺陷而出现的。它的用法和 sizeof 很相似:

decltype(表达式)

在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。
有时候,我们可能需要计算某个表达式的类型,例如:

auto x = 1;
auto y = 2;
decltype(x+y) z;

拖尾返回类型、auto 与 decltype 配合
你可能会思考,auto 能不能用于推导函数的返回类型。考虑这样一个例子加法函数的例子,在传统 C++ 中我们必须这么写:

template<typename R, typename T, typename U>
R add(T x, U y) {
    return x+y
}
这样的代码其实变得很丑陋,因为程序员在使用这个模板函数的时候,必须明确指出返回类型。但事实上我们并不知道 add() 这个函数会做什么样的操作,获得一个什么样的返回类型。

在 C++11 中这个问题得到解决。虽然你可能马上回反应出来使用 decltype 推导 x+y 的类型,写出这样的代码:

decltype(x+y) add(T x, U y);
但事实上这样的写法并不能通过编译。这是因为在编译器读到 decltype(x+y) 时,x 和 y 尚未被定义。为了解决这个问题,C++11 还引入了一个叫做拖尾返回类型(trailing return type),利用 auto 关键字将返回类型后置:

template<typename T, typename U>
auto add(T x, U y) -> decltype(x+y) {
    return x+y;
}

从 C++14 开始是可以直接让普通函数具备返回值推导,因此下面的写法变得合法:

template<typename T, typename U>
auto add(T x, U y) {
    return x+y;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值