C++17 详解 25 —标准库的其它变动

本文为 《C++17 in detail》 一书的中文渣中渣译文,不足之处还望指正。

翻译太特么累人了……剩余部分还是只做摘要翻译吧。

14. STL 其它改动

14.1 std::byte

类型安全的字节表示,不是数值型值。

定义:

1
enum class byte : unsigned char {} ; // in <cstddef>

可以通过 unsigned char 初始化 b{unsigned char},也可以通过 std::to_integer() 转换成数值类型。

14.2 map 和 set 改进

拼接(splicing)

新函数:set/map::extract()

1
2
3
4
5
std::set<User> setNames;
setNames.emplace("John");
std::set<User> outSet;
auto handle = setNames.extract(User("John"));
outSet.insert(std::move(handle));

将 John 从 setNames 提取出来,然后把它插入 outSet。

  • extract 返回 node_type 类型的节点句柄
  • node_handle 是一个只可移动类型,移动构造函数从对象中取走容器元素所有权。
  • User 不需要定义移动构造函数就可以使用 extract(node_handle 持有 node*node* 持有 User)。

对 map 和 unordered_map 的 emplace 加强

  1. 新加 try_emplace() 函数:如果指定键值已经存在不做任何事情,否则执行 emplace()。

  2. 新加 insert_or_assign() 函数:插入新键值对或更新已存在键的值,值以移动构造方式转移进容器。

14.3 emplace 函数的返回值类型

由 void 改为了 T&

1
2
3
4
5
6
7
// C++17 前的 std::vector
template< class... Args >
void emplace_back( Args&&... args );

// C++17 的 std::vector
template< class... Args >
reference emplace_back( Args&&... args );

14.4 采样算法

std::sample:从序列中选择 n 个元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <random>
#include <iterator>
#include <algorithm>

int main() {
std::vector<int> v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::vector<int> out;
std::sample(v.begin(),
v.end(),
std::back_inserter(out),
3, // 采样数量
std::mt19937{std::random_device{}()});

std::cout << "Sampled values: ";
for (const auto &i : out)
std::cout << i << ", ";
}

14.5 新的数学函数

<numerics> 头文件:

  • std::gcd:最大公约数
  • std::lcm:最小公倍数

<algorithm> 头文件:

  • std::clamp(v, min, max)

<cmath> 头文件:

  • assoc_laguerre
  • assoc_legendre
  • beta
  • comp_ellint_1
  • comp_ellint_2
  • comp_ellint_3
  • cyl_bessel_i
  • cyl_bessel_j
  • cyl_bessel_k
  • cyl_neumann
  • ellint_1
  • ellint_2
  • ellint_e
  • expint
  • hermite
  • laguerre
  • legendre
  • riemann_zeta
  • sph_bessel
  • sph_legendre
  • sph_neumann

译注:完全没了解。

14.6 shared_ptr 和数组

现在 shared_ptr 持有数组不需要指明自定义 deleter 了:

1
std::shared_ptr<int[]> ptr(new int[10]);

make_shared 还不支持数组,需要等到 C++20。

14.7 非成员的 size()、data()、empty()

头文件:

1
#include <iterator>

14.8 标准库里 constexpr 的增加

C++17 开始添加容器类的 constexpr 构造能力;C++20 添加 constexpr 算法的能力。

14.9 std::scoped_lock

scoped_lock 可以对多个 mutex 同时 lock:

1
std::scoped_lock lck(first_mutex, second_mutex);

14.10 std::iterator 被弃用

自定义迭代器类时不需要再从 std::iterator 继承,虽然需要显式地定义类型萃取的各个部分,但是代码变得更清晰了。

旧:

1
2
3
4
5
class ColumnIterator
: public std::iterator<std::random_access_iterator_tag, Column>
{
// ...
};

新:

1
2
3
4
5
6
7
8
9
class ColumnIterator {
public:
using iterator_category = std::random_iterator_tag;
using value_type = Column;
using difference_type = std::ptrdiff_t;
using pointer = Column*;
using reference = Column&;
// ...
};

14.11 多态化的分配器(Allocator),pmr

https://en.cppreference.com/w/cpp/header/memory_resource

预置了几种不同内存分配策略的分配器。

pmr:Polymorphic Memory Resource,多态内存资源。

评论