C++17 详解 2
本文为 《C++17 in detail》 一书的中文渣中渣译文,不足之处还望指正。
1. 修复和弃用
C++17 标准现在有超过 1600 页,比 C++14 多出了 200 多页。幸运的是,语言规范在一些地方得到了清理,一些老旧的或潜在的坏特性随之被清除。
本章你将学到:
- 从语言中删除了什么,比如:
register
关键字,auto_ptr
和std::random_shuffle
。 - 已弃用并会在未来版本被删除的内容。
- 修复内容,尤其是对“花括号初始化”(
brace initialisation
)的自动类型推导。
1.1 删除内容
每次 C++ 版本迭代,其中一个核心概念就是和旧版本的兼容性。我们期待语言中出现新东西,同时我们的老工程应该仍然能编译通过。尽管如此,有时候这也是一个删除极少用到或错误部分的机会。
译注:老外说话有时候就是别别扭扭,不够直接。上边这段话大概就是“向下兼容当然是首要的,但有时候不得不删除一些很少用到的或者是错误的东西”的意思。
本节简要说明从标准中删除的内容。
1.1.1 删除 auto_ptr
可能是最好的消息了!
C++98 加入 auto_ptr
,做为对原生指针支持基本的 RAII 特性的手段。但是,由于当时语言中缺少移动语义,auto_ptr
很容易被误用从而导致运行时错误。
这里是一个 auto_ptr
可能导致崩溃的例子:
1 | // Chpater Fixes And Deprecation/auto_ptrCrash.cpp |
doSomething()
通过传值参数拿到指针,但是 auto_ptr
不是共享型指针(shared pointer
),所以它拿到了被管理对象的唯一所有权。当函数执行完毕,pyPtr
走完生命周期,指针对象被删除。
在 AutoPtrTest()
中,当 doSomething
结束时指针对象已经被删除了,接下来(译注:*myTest = 12;
)你会触发未定义行为(undefined behavior
),甚至可能崩溃。
译注:原文
maybe even a crash!
。实际触发ub
时,崩溃可能是最好的结果了,很大程度免去了把 bug 带到线上的痛苦。
到 C++11,我们有了智能指针:unique_ptr
、shared_ptr
和 weak_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。