「生活可以更简单, 欢迎来到我的开源世界」
  1. 语言层面
    1. 关于模板的改进
C++11/14新特性学习笔记
2020-01-10
C++

闲暇之余,在B站看到了侯捷老师的C++2.0课程视频,通过学习,了解了C++2.0的一些新特性。侯捷老师的课程从语言层面和标准库层面分别介绍了这些新特性。

语言层面

通过输出打印宏定义“__cplusplus”的值可以查看编译器提供的版本。若数字大于等于201103,则表示支持C++11。

#include <iostream>

using std::cout;
using std::endl;

int main(int argc, char* argv[]){
cout << __cplusplus << endl;
return 0;
}

//--std=c++2a -> 201709
//--std=c++17 -> 201703
//--std=c++14 -> 201402
//--std=c++11 -> 201103
//我的环境下不加编译选项 -> 201402

关于模板的改进

  1. 模板的右尖括号

    C++1.0是不允许两个右尖括号连在一起出现的,会被认为是右移操作符,所以在C++11之前的模板会用空格将两个右尖括号分开。

    C++11之后就不需要这样了。

    #include <iostream>
    #include <vector>

    using std::cout;
    using std::endl;
    using std::vector;

    int main(int argc, char* argv[]){
    cout << __cplusplus << endl;
    vector<vector<char>> a;
    return 0;
    }
    //--std=c++98
    //error: '>>' should be '> >' within a nested template argument list
  1. 别名模板

    template <模板形参类表>
    using 标识符 attr(可选) = 类型标识;

    C++11引入了using定义别名的方法,可替代typedef,使得定义别名更加通俗易懂。typedef是不接受参数的,也就无法使用别名模板的模板实参替换类型标识。

    与任何模板声明相似,别名模版仅可声明于类作用域或命名空间作用域。

在推导模板模板形参时,模板实参推导始终不推导别名模板。不可能部分特化或显式特化别名模板。

    template <class T>
struct Alloc {};
template <class T>
using Vec = std::vector<T, Alloc<T>>;
Vec<int> coll; //等同于std::vector<int, Alloc<int>>



​ template <typename T>
​ struct Container{
​ using value_type = T;
​ }
​ template <typename ContainerType>
​ void g(const ContainerType& c){
​ typename ContainerType::value_type n;
​ }
​ ```




### 指针字面量:nullptr

关键词 nullptr 代表指针字面量。它是 std::nullptr_t 类型的纯右值。存在从 nullptr 到任何指针类型及任何成员指针类型的隐式转换。

std::nullptr_t 是空指针字面量 nullptr 的类型。它是既非指针类型亦非指向成员指针类型的独立类型。

#include
#include

template<class F, class A>
void Fwd(F f, A a)
{
f(a);
}

void g(int* i)
{
std::cout << “Function g called\n”;
}

int main()
{
g(NULL); // 良好
g(0); // 良好

Fwd(g, nullptr);   // 良好

// Fwd(g, NULL); // 错误:不存在函数 g(int)
}


宏 `NULL` 是实现定义的空指针常量,C++11后可能为零值整数字面量,或为 std::nullptr_t 类型纯右值。

#define NULL 0
//C++11起
#define NULL nullptr


### 占位符类型说明符:auto

对于变量,指定要从其初始化器自动推导出其类型。

对于函数,指定要从其 return 语句推导出其返回类型。 (C++14 起)

对于非类型模板形参,指定要从实参推导出其类型。 (C++17 起)

//auto 常用于无名类型,例如 lambda 表达式的类型
auto lambda = [](int x) { return x + 3; };

//auto 常用于迭代器类型
vecotr a;
auto i = a.begin();

template // C++17 auto 形参声明
auto f() -> std::pair<decltype(n), decltype(n)> // auto 不能从花括号初始化器列表推导
{
return {n, n};
}
```

<⇧>