Hello World

行走即是圆梦,回望亦是前行。

0%

c++11学习笔记

前言

这里简单记录下《深入应用c++11 祁宇 著》的学习笔记

c++11学习笔记 《深入应用c++11 祁宇 著》
作者博客
GitHub地址

第一篇 改进我们的程序

第1章 使用C++11让程序更简洁、更现代

1-1 类型推导auto decltype

  • auto的推导规则:

    当不声明为指针或者引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后的类型一致;
    当声明为指针或者引用时,auto的推导结果将保持初始化表达式的cv限定符属性;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //存储说明符
    auto //...
    register //修饰符暗示编译程序相应的变量将被频繁地使用,不能& https://blog.csdn.net/21aspnet/article/details/257511
    static //...
    extern //告诉编译器是外部变量
    mutable //修饰的变量,将永远处于可变的状态,突破const
    //cv限定符
    const //...
    volatile //防止编译器优化
  • auto的限制

    1. 不能用于函数参数
    2. 不能用于非静态const成员变量
    3. 无法定义数组
    4. 无法推导出模板参数
  • decltype的推导规则

    1
    decltype(exp)
    1. exp是标识符、类访问表达式,decltype(exp)和exp的类型一致
    2. exp是函数调用,decltype(exp)和和exp的返回值类型一致
    3. 若exp是一个左值,则decltype(exp)是exp类型的左值引用,否则和exp类型一致

    规则2备注说明 对于纯右值而言,只有class类型会保留cv限定符,其他一般忽略掉cv限定,如下:

    ??? vs2019测试结果和该说法不符,class类型也会忽略cv限定

    1
    2
    3
    4
    5
    6
    7
    class Foo {}

    const int func_cint(void); //纯右值
    const Foo func_cfoo(void); //纯右值

    decltype(func_cint()) a = 0; //a-->int
    decltype(func_cfoo()) f = Foo(); //f-->const Foo ??? vs2019 -->Foo

    规则3备注说明 带括号的表达式和加法运算表达式

    foo.x 是左值,可知(foo.x)也是左值,因此decltype的结果是右值引用
    foo是const,foo.x是一个const int类型左值,所以decltype的结果是const int&
    m + n 返回一个右值;m += n 返回一个左值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct Foo { int x; };
    const Foo foo = Foo();

    decltype(foo.x) a = 0; //a-->int
    decltype((foo.x)) b = a; //b-->const int&

    int m = 0, n = 0;
    decltype(m + n) c = 0; //c-->int
    decltype(m += n) d = a; //d-->const int&
  • 返回类型后置语法–autodecltype的结合使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    template<typename T, typename U>
    auto add(T t, U u) -> decltype(t + u) {
    return (t + u);
    }
    auto x = add(1, 2.0);

    //////////////////////////////
    int& foo(int& i) { return i; };
    float foo(float& f) { return f; };

    template<typename T>
    auto func(T& val) ->decltype(foo(val)) {
    return foo(val);
    }
    int i = 0;
    auto x = func(i);
  • autodecltype的区别

    1. auto修饰的的变量必须初始化;decltype可以推导未初始化的变量
    2. decltype可以获得表达式的类型,并且可以推导出定义本身的类型,不会像auto可能丢弃引用和cv限定符

1-2 模板的细节改进

c++11改进了编译器的解析规则,尽可能地将多个右尖括号(>)解析成模板参数结束符

  1. c++98/03的泛型编程中,连续两个右尖括号(>>)会被编译器解释成右移操作符,而不是模板参数表的结束;
  2. Foo<A<int>>这种写法不被支持,要写成Foo<A<int> >注意两个右尖括号之间的空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename Val>
using xxx_map_t = std::map<std::string, Val>;

//c++98/03
template<typename T>
struct func_t1 {
typedef void (*type)(T, T);
};
func_t1<int>::type xx_1;

//c++11
template<typename T>
using func_t2 = void (*)(T, T);
func_t2<int> xx_2;
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
struct identity {
typedef T type;
};

template<typename T = int>
void func(typename identity<T>::type val, T = 0) {
std::cout << typeid(T).name() << ", " << val << std::endl;
}

func(123); //T-->int
func(123, 123.456) //T-->double
  1. 当默认模板参数和模板参数自动推导同时使用时,若函数模板无法自动推导出参数类型,则编译器将使用自动推导出的参数类型;否则将使用自动推导类型
  2. identity外敷模板 禁用了形参val的类型自动推导 ,由于func制定了模板参数T默认为int,因此func(123)的val参数为int类型;在func(123, 123.456)的第二参数为 double类型,模板参数T将优先自动推导为double,因此func(123, 123.456)的val参数为double类型

ps. 默认模板参数不是模板参数自动推导的“建议”,模板参数自动推导总是根据实参推导来的,当自动推导类型生效时,默认模板参数类型会被忽略

1-3 列表初始化

1-4 基于范围的for循环

第2章 使用C++11改进程序性能

[TODO]

第3章 使用C++11消除重复,提高代码质量

[TODO]

第4章 使用C++11解决内存泄露的问题

[TODO]

第5章 使用C++11让多线程开发变得简单

[TODO]

第6章 使用C++11中便利的工具

[TODO]

第7章 使用C++11的其他特征

[TODO]

第二篇 C++11工程级应用

第8章 使用C++11改进我们的模式

[TODO]
查看源码

第9章 使用C++11开发一个半同步半异步线程池

原文博客
查看源码

第10章 使用C++11开发一个轻量级的AOP库

原文博客
查看源码

第11章 使用C++11开发一个轻量级的IoC容器

原文博客
[DOING]
p267
查看源码

第12章 使用C++11开发一个对象的消息总线库

原文博客
[TODO]
查看源码

第13章 使用C++11封装sqlite库

原文博客
[TODO]
查看源码

第14章 使用C++11开发一个linq to objects库

[TODO]
查看源码

第15章 使用C++11开发一个轻量级的并行task库

原文博客
[TODO]
查看源码

第16章 使用C++11开发一个简单的通信程序

原文博客
查看源码