C++11 新特性学习

在Linux下编译C++11

#include<typeinfo>
int main()
{
    auto a=10;
    cout<<typeid(a).name()<<endl;    //得到a的类型,只是一个字符串
    return 0;   
}

编译需要加-std=c++11,如下例:

0.98332977099667

auto

C++11中引入auto第一种作用是为了自动类型推导

auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作

auto实际上实在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响

另外,似乎auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。

auto a; // 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定a的类型  
auto i = 1; 
auto d = 1.0; 
auto str = "Hello World"; 
auto ch = 'A'; 
auto func = less<int>(); 
vector<int> iv; 
auto ite = iv.begin(); 
auto p = new foo() // 对自定义类型进行类型推导

auto不光有以上的应用,它在模板中也是大显身手,比如下例这个加工产品的例子中,如果不使用auto就必须声明Product这一模板参数:

template <typename Product, typename Creator>  
void processProduct(const Creator& creator) { 
    Product* val = creator.makeObject(); 
    // do somthing with val 
}
如果使用auto,则可以这样写:
template <typename Creator> 
void processProduct(const Creator& creator) {  
    auto val = creator.makeObject(); 
    // do somthing with val 
}

抛弃了麻烦的模板参数,整个代码变得更加正解了。

decltype

decltype实际上有点像auto的反函数,auto可以让你声明一个变量,而decltype则可以从一个变量或表达式中得到类型,有实例如下:

int x = 3;  
decltype(x) y = x;
有人会问,decltype的实用之处在哪里呢,我们接着上边的例子继续说下去,如果上文中的加工产品的例子中我们想把产品作为返回值该怎么办呢?我们可以这样写:
template <typename Creator>  
auto processProduct(const Creator& creator) -> decltype(creator.makeObject()) {  
    auto val = creator.makeObject();  
    // do somthing with val  
}

typeid().name()与decltype

typeid().name得到的仅仅是一个字符串

而decltype可以提取出类型

nullptr

nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,因为NULL实际上代表的是0

void F(int a){  
    cout<<a<<endl;  
}  
 
void F(int *p){  
    assert(p != NULL);  
 
    cout<< p <<endl;  
}  
 
int main(){  
 
    int *p = nullptr;  
    int *q = NULL;  
    bool equal = ( p == q ); // equal的值为true,说明p和q都是空指针  
    int a = nullptr; // 编译失败,nullptr不能转型为int  
    F(0); // 在C++98中编译失败,有二义性;在C++11中调用F(int)  
    F(nullptr);  
 
    return 0;  
}

序列for循环

在C++中for循环可以使用类似java的简化的for循环,可以用于遍历数组,容器,string以及由begin和end函数定义的序列(即有Iterator),示例代码如下:

map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};  
for (auto p : m){  
    cout<<p.first<<" : "<<p.second<<endl;  
}

更加优雅的初始化

在引入C++11之前,只有数组能使用初始化列表,其他容器想要使用初始化列表,只能用以下方法:

int arr[3] = {1, 2, 3};
vector<int> v(arr, arr + 3);

在C++11中,我们可以使用以下语法来进行替换:

int arr[3]{1, 2, 3};
vector<int> iv{1, 2, 3};
map<int, string>{{1, "a"}, {2, "b"}};
string str{"Hello World"};

alignof和alignas 

C++11标准中,为了支持对齐,引入了两个关键字:操作符alignof和对齐描述符alignas。

操作符alignof:用于返回类的对齐方式,即对齐值

对齐描述符alignas:用于设置类使用哪种对齐方式

struct alignas(32) A
{
    char a;
    int b;
};
 
int main()
{
    //由于用alignas设置了对齐方式,原本大小为8字节的类A变为32字节了
    cout << sizeof(A) << endl;       //输出:32
    cout << alignof(A) << endl;      //输出:32
 
    //alignas既可以接受常量表达式,也可以接受类型作为参数
    alignas(8) int a;
    alignas(alignof(double)) int b;
}

  C++11标准中规定了一个“基本对齐值”。一般情况下其值等于平台上支持的最大标量类型数据的对齐值。我们可以通过alignof(std::max_align_t)来查询其值。而像之前我们把对齐值设置为32位的做法称为扩展对齐,这按照C++标准该程序是不规范的,可能会导致未知的编译错误或者运行时错误。

  其余对齐方式有STL库函数(std::align),还有STL库模板类型(aligned_storage和aligned_union)。

Lambda表达式

见另一篇:https://www.cnblogs.com/WindSun/p/11182276.html

原文地址:https://www.cnblogs.com/WindSun/p/11336631.html