C++新标准

C++ 11

语法特性:

  • auto
  • decltype
  • 返回类型后置(auto+decltype)
  • 右值引用
  • 列表初始化
  • 移动语义(std::move)
  • 万能引用(T&&)
  • 智能指针(share_ptr; wake_ptr; unique_ptr)
  • 范围for循环
  • 委托构造函数
  • 继承构造函数
  • finaloverride
  • default
  • 函数delete
  • explicit
  • constexpr
  • 强类型枚举(enum class)
  • 原始字符串字面量
  • 基于范围的for循环
  • lambda表达式
  • 内联命名空间
  • >的优化
  • noexcept
  • char32_tchar16_t

库特性:

  • chrono

  • thread

  • std::function

  • std::bind

  • std::move

  • std::forword:与万能引用配合使用

  • std::array

  • std::to_string()

  • std::tuple(元组)

  • std::tie

  • std::ref

  • std::make_shared

  • 无序容器:

    • std::unordered_map
    • std::unordered_multimap
    • std::unordered_set
    • std::unordered_multiset
  • 内存模型

  • std::async

  • std::forward_list(单链表)

C++ 14

  • 变量模板

  • 泛型lambda参数

  • lambda初始化捕获

  • 放宽constexptr函数限制

    在C++11中,constexpr函数的限制非常严格,要求其函数体仅能包含一个返回语句,且不能包含复杂的控制流语句(如循环、条件分支等)。

    1
    2
    3
    4
    // C++11 constexpr阶乘函数的写法,只能使用递归
    constexpr int factorial(int n) {
    return n <= 1 ? 1 : (n * factorial(n - 1));
    }

    而在C++14中,允许在其函数体内使用更复杂的控制流结构和局部变量声明,也可以有多个返回语句,只要最终的结果能够在编译时计算得出即可。

    1
    2
    3
    4
    5
    6
    7
    8
    // C++14 constexpr阶乘函数的写法,可以使用循环
    constexpr int factorial(int n) {
    int ret = 0;
    for (int i = 0; i < n; ++i) {
    ret += i;
    }
    return ret;
    }
  • [[deprecated]](废弃标志)

    标记已弃用的函数、类或其他声明。这有助于编译器在编译时发出警告,提醒开发者不应再使用某个已标记为过时的API

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [[deprecated]]
    void TriassicPeriod() {
    std::clog << "Triassic Period: [251.9 - 208.5] million years ago.\n";
    }

    [[deprecated("Use NeogenePeriod() instead.")]] // 弃用并标明弃用原因
    void JurassicPeriod() {
    std::clog << "Jurassic Period: [201.3 - 152.1] million years ago.\n";
    }
  • std::shared_timed_mutex

    超时读写锁。shared_timed_mutex

  • std::shared_lock

  • std::make_unique

  • std::exchange

    原子地交换一个对象的值,并返回其旧值。这个函数在处理资源管理、状态转换等场景时特别有用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    #include <iostream>
    #include <iterator>
    #include <utility>
    #include <vector>

    class stream
    {
    public:
    using flags_type = int;

    public:
    flags_type flags() const { return flags_; }

    // Replaces flags_ by newf, and returns the old value.
    flags_type flags(flags_type newf) { return std::exchange(flags_, newf); }

    private:
    flags_type flags_ = 0;
    };

    void f() { std::cout << "f()"; }

    int main()
    {
    stream s;

    std::cout << s.flags() << '\n';
    std::cout << s.flags(12) << '\n';
    std::cout << s.flags() << "\n\n";

    std::vector<int> v;

    // Since the second template parameter has a default value, it is possible
    // to use a braced-init-list as second argument. The expression below
    // is equivalent to std::exchange(v, std::vector<int>{1, 2, 3, 4});

    std::exchange(v, {1, 2, 3, 4});

    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ", "));

    std::cout << "\n\n";

    void (*fun)();

    // The default value of template parameter also makes possible to use a
    // normal function as second argument. The expression below is equivalent to
    // std::exchange(fun, static_cast<void(*)()>(f))
    std::exchange(fun, f);
    fun();

    std::cout << "\n\nFibonacci sequence: ";
    for (int a{0}, b{1}; a < 100; a = std::exchange(b, a + b))
    std::cout << a << ", ";
    std::cout << "...\n";
    }

    输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    0
    0
    12

    1, 2, 3, 4,

    f()

    Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
  • std::quoted

    具体使用案例:(来自cppreference

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #include <iomanip>
    #include <iostream>
    #include <sstream>

    void default_delimiter()
    {
    const std::string in = "std::quoted() quotes this string and embedded \"quotes\" too";
    std::stringstream ss;
    ss << std::quoted(in);
    std::string out;
    ss >> std::quoted(out);

    std::cout << "Default delimiter case:\n"
    "read in [" << in << "]\n"
    "stored as [" << ss.str() << "]\n"
    "written out [" << out << "]\n\n";
    }

    void custom_delimiter()
    {
    const char delim{'$'};
    const char escape{'%'};

    const std::string in = "std::quoted() quotes this string and embedded $quotes$ $too";
    std::stringstream ss;
    ss << std::quoted(in, delim, escape);
    std::string out;
    ss >> std::quoted(out, delim, escape);

    std::cout << "Custom delimiter case:\n"
    "read in [" << in << "]\n"
    "stored as [" << ss.str() << "]\n"
    "written out [" << out << "]\n\n";
    }

    int main()
    {
    default_delimiter();
    custom_delimiter();
    }

    输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Default delimiter case:
    read in [std::quoted() quotes this string and embedded "quotes" too]
    stored as ["std::quoted() quotes this string and embedded \"quotes\" too"]
    written out [std::quoted() quotes this string and embedded "quotes" too]

    Custom delimiter case:
    read in [std::quoted() quotes this string and embedded $quotes$ $too]
    stored as [$std::quoted() quotes this string and embedded %$quotes%$ %$too$]
    written out [std::quoted() quotes this string and embedded $quotes$ $too]

C++ 17

C++ 20

[ddd]: