c++11 -14 (一)关键字(alignas、alignof、bitand和bitor、constexpr、const_cast、decltype、后置返回值类型、dynamic_cast)

C++资源

https://isocpp.org/blog/2014/03/compiler-support-for-c11-and-c14

http://www.stroustrup.com/

推荐工具软件——DASH。这个查语言特性特别快。只可惜只能在苹果系的产品中使用。

 


关键字

/* key words of cpp
 * alignas (C++11 起)
 * alignof (C++11 起)
 * and
 * and_eq
 * asm
 * auto
 * bitand
 * bitor
 * bool
 * break
 * case
 * catch
 * char == unsigned char linux signed char
 * char16_t(C++11 起)Unicode utf8
 * char32_t(C++11 起)Unicode
 * class
 * compl ~
 * concept (概念TS)
 * const   multithread
 * constexpr(C++11 起)
 * const_cast
 * continue
 * decltype(C++11 起)
 * default (normal use        speical use)
 * delete
 * do
 * double
 * dynamic_cast
 * else
 * enum
 * explicit
 * export
 * extern
 * false
 * float
 * for
 * friend
 * goto
 * if
 * inline
 * int signed
 * long
 * mutable
 * namespace
 * new
 * noexcept(C++11 起)
 * not !
 * not_eq !=
 * nullptr (C++11 起)
 * operator + - ||
 * or ||
 * or_eq |=
 * private
 * protected
 * public
 * register
 * reinterpret_cast
 * requires(概念TS)
 * return
 * short
 * signed
 * sizeof
 * static
 * static_assert(C++11 起)
 * static_cast
 * struct
 * switch
 * template
 * this
 * thread_local(C++11 起)
 * throw
 * true
 * try
 * typedef
 * typeid
 * typename
 * union
 * unsigned
 * using
 * virtual
 * void
 * volatile
 * wchar_t
 * while
 * xor ^
 * xor_eq ^=
 * */

 

 

alignas——取值是2的幂次

用来对结构体或者类设置对齐方式

struct alignas(8) S {};

//下面的是错误的,因为S的对其凡事要求是8,因此,U的对齐方式不能小于8
struct alignas(1) U { S s; };

 

 

alignof

用来获取结构体是按照多少字节对齐的

struct Obj {
	char a;
	int b;
};

sizeof(Obj);//8
alignof(Obj);//4  因为结构体Obj是按四字节对齐的

测一测

struct Foo {
	int i;
	float f;
	char c;
};

class Empty{};

struct alignas(64) Empty64 {};

struct alignas(1) Double { doubel i; };

struct Obj {
	char a;
	int b;
};

void alignInof() {
	cout << alignof(char) << endl;
	cout << alignof(int *) << endl;//64位平台是8,32位平台是4
	cout << alignof(Foo) << endl;//4,因为int是4,float也是4
	cout << alignof(Empty) << endl;//1
	cout << alignof(Empty64) << endl;//64
	cout << alignof(Double) << endl;//8,虽然设置的对齐数是1,但是double占8字节
}

 

 

bitand和bitor

按位与和按位或

#include<iostream>
using namespace std;

int main(){
	auto a=3L;
	auto b=4;
        //按位与的过程中,b转型为长整型,因此c的类型也是长整型
	auto c=a bitand b;
	auto d=a bitor b;
	
	cout<<"type of c :"<<typeid(c).name()<<endl;
	cout<<"type of b:"<<typeid(b).name()<<endl;
	cout<<"value of c:"<<c<<endl;
	cout<<"value of d:"<<d<<endl;
	return 0;
}

 

 

 

constexpr

用代码求阶乘的方法如下

int fact(int n) {
	return n < 1? 1: (n * fact(n-1));
}

我们将其进行修改

constexpr int factorial(int n) { 
    return n <= 1 ? 1 : (n * factorial(n - 1)); 
}

此时,对于阶乘的求解会发生如下变化:

  • 编译期,如果传入的参数n的值在编译器可以确定出来,则在编译器直接求出函数的结果。
  • 求出结果之后,在运行期就直接将结果放在了调用该函数的地方

 

未完待续,constexpr的其他特性在以后进行补充

 

 

const_cast——将const类型变成非const类型

如果代码中出现const_cast,说明代码的结果或者风格可能有一些问题。

const的不变性可以通过const_cast来改变。

void testConstCast(){
    const int i=3;
    int *p=const_cast<int*>(&j);
    *p=4;
}

 

 

 

decltype

为变量设置类型

下面代码中是decltype的两种使用方式:

struct A{ double x; };

void testDecl(){
    const A* a = new A{0};
    decltype (a->x) y;       //y的类型为double,因为a->x的类型是double
    decltype ((a->x)) z=y;   //z的类型的double&,cpp里面,对于decltype,带括号的就是获取引用
}

 

 

后置返回值类型

(cpp 11新特性。返回值类型由计算结果决定,防止返回值精度的丢失。)

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

为什么不能写成

template<typename T, typename U>
decltype(a+b) add(T a, U b){
    return a+b;
}

因为编译器运行到decltype那一行的时候,读到a,但是a的类型此时还未声明,因此,编译器会报错。

在cpp14中,对于后置返回值类型进行了简化。因此代码可以这么写:

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

 

再次强调一遍,注意()(PS:代码是伪代码,只是为了表达意思,一个函数里面是不能这么写两个return 语句的)

template<typename T, typename U>
auto add(T a, U b){
    auto c=a+b;
    return c;       //返回值类型是c的类型
    return (c);     //返回值类型是c的引用。如果c是int类型,则该返回值类型是int&
}

但是如果写成cpp 11版本的返回值后置,则上述两种的返回值类型由decltype语句决定,即

template<typename T, typename U>
auto add(T a, U b) -> decltype(a+b){
    auto c=a+b;
    return c;       //返回值类型是decltype(a+b)的类型
    return (c);     //返回值类型是decltype(a+b)的类型
}

 

 

 

dynamic_cast——将父类指针转换成子类指针

  • dynamic_cast对于引用,如果转换失败,则抛出异常
  • dynamic_cast对于指针,如果转换失败,则返回空指针
  • dynamic_cast会在转化过程中会进行安全检查,因此会比其他cast更安全

dynamic_cast的详细解释见:(占位,以后专门写篇博客补在这里)

struct Base{virtual ~Base(){}};

struct Derived : Base {
  virtual void name() {}
};

void testDyn() {
	Base *b1 = new Base;
	//如果dynamic_cast转换失败,则会返回空指针
	if (Derived *d = dynamic_cast<Derived *>(b1)) {
		std::cout << "downcast from b1 to d successful\n";
		d->name(); // safe to call
	}

	Base *b2 = new Derived;
	//如果dynamic_cast转换成功,则会返回该类型的指针(非空)
	if (Derived *d = dynamic_cast<Derived *>(b2)) {
		std::cout << "downcast from b2 to d successful\n";
		d->name(); // safe to call
	}
	Base bb;
	//dynamic_cast对于引用,如果转换失败,则抛出异常
	Derived& cc = dynamic_cast<Derived&>(bb);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值