C++17 详解 2

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

1. 修复和弃用

C++17 标准现在有超过 1600 页,比 C++14 多出了 200 多页。幸运的是,语言规范在一些地方得到了清理,一些老旧的或潜在的坏特性随之被清除。

本章你将学到:

  • 从语言中删除了什么,比如:register 关键字,auto_ptrstd::random_shuffle
  • 已弃用并会在未来版本被删除的内容。
  • 修复内容,尤其是对“花括号初始化”(brace initialisation)的自动类型推导。

1.1 删除内容

每次 C++ 版本迭代,其中一个核心概念就是和旧版本的兼容性。我们期待语言中出现新东西,同时我们的老工程应该仍然能编译通过。尽管如此,有时候这也是一个删除极少用到或错误部分的机会。

译注:老外说话有时候就是别别扭扭,不够直接。上边这段话大概就是“向下兼容当然是首要的,但有时候不得不删除一些很少用到的或者是错误的东西”的意思。

本节简要说明从标准中删除的内容。

1.1.1 删除 auto_ptr

可能是最好的消息了!

C++98 加入 auto_ptr,做为对原生指针支持基本的 RAII 特性的手段。但是,由于当时语言中缺少移动语义,auto_ptr 很容易被误用从而导致运行时错误。

这里是一个 auto_ptr 可能导致崩溃的例子:

1
2
3
4
5
6
7
8
9
10
11
12
// Chpater Fixes And Deprecation/auto_ptrCrash.cpp

void doSomething(std::auto_ptr<int> myPtr)
{
*myPtr = 11;
}

void AutoPtrTest() {
std::auto_ptr<int> myTest(new int(10));
doSomething(myTest);
*myTest = 12;
}

doSomething() 通过传值参数拿到指针,但是 auto_ptr 不是共享型指针(shared pointer),所以它拿到了被管理对象的唯一所有权。当函数执行完毕,pyPtr 走完生命周期,指针对象被删除。

AutoPtrTest() 中,当 doSomething 结束时指针对象已经被删除了,接下来(译注:*myTest = 12;)你会触发未定义行为(undefined behavior),甚至可能崩溃。

译注:原文 maybe even a crash!。实际触发 ub 时,崩溃可能是最好的结果了,很大程度免去了把 bug 带到线上的痛苦。

到 C++11,我们有了智能指针:unique_ptrshared_ptrweak_ptr。配合移动语义,C++ 终于可以正确支持唯一资源的转移了。而且新的智能指针可以被存储在标准容器内,auto_ptr 是不支持的。你应该用 unique_ptr 替换掉 auto_ptr,因为它是 auto_ptr 直接的、最好的对等物。

新的智能指针相比 auto_ptr 更强大更安全,所以从 C++11 起 auto_ptr 已经被标记为已弃用。编译器会报出一个 warning:

warning: 'template<class> class std::auto_ptr' is deprecated

现在,如果你用一个合规的 C++17 编译器编译,它会报出一个 error。

这是启用 /std:c++latest 选项的 MSVC 2017 报出的 error:

1
error C2039: 'auto_ptr': is not a member of 'std'

如果你需要从 auto_ptr 转换到 unique_ptr 的帮助,可以查阅 Clang Tidy,它提供了自动转换: Clang Tidy: modernize-replace-auto-ptr

译注:Clang-Tidy 是一套基于 Clang 的静态检查工具,其中一项功能就是自动替换 auto_ptr

扩展:本修改提案:N4190

评论