C++17 详解 3

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

1.1.2 删除关键字 register

关键字 register 在 2011 年(C++11)被弃用,自那以后 register 已经没有意义,现在它被删除。这个关键字仍然被保留,有可能会在未来某个版本重新设计意图(比如关键字 auto 就是复用而来,现在它是一个全新的、更强大的特性)。

如果你用 register 声明变量:

1
register int a;

可能会产生如下 warning(GCC8.1):

1
warning: ISO C++17 does not allow 'register' storage class specifier

或是 Clang 的一个 error(Clang 7.0):

1
error: ISO C++17 does not allow 'register' storage class specifier

扩展:本修改提案:P0001R1

1.1.3 删除弃用的 operator++(bool)

这个操作符已经被弃用很久了。标准委员会早在 1998 年(C++98)就建议不要使用,但直到现在他们才达成一致,把它从标准里删除。

译注:C++ 标准委员会出了名的松散、低效,学院气十足。此处即可见一斑,遑论如网络库、协程库等模块级的更新效率。

如果你尝试编译如下代码:

1
2
bool b;
b++;

会生成像下边 GCC(GCC 8.1)类似的 error:

1
error: use of an operand of type 'bool' in 'operator++' is forbidden in C++17

扩展:本修改提案:P0002R1

1.1.4 删除弃用的异常规范

C++17 里,异常规范是类型系统的一部分(在下一章“语言声明”有讨论)。但是标准还是保留了以前被弃用的异常规范,只是没有实际作用。

比如:

1
2
3
4
5
void fooThrowsInt(int a) throw(int) {
printf_s("can throw ints\n");
if (a == 0)
throw 1;
}

请特别留意 throw(int)

上边的代码在 C++11 已经被弃用,现在唯一可行的异常声明是 throw(),意思是这段代码绝不会抛出任何异常。C++11 起建议用 noexcept 代替。

比如 clang 4.0 里会生成如下 error:

1
2
error: ISO C++1z does not allow dynamic exception specifications
[-Wdynamic-exception-spec] note: use 'noexcept(false)' instead

扩展:本修改提案:P0003R5

1.1.5 其它被删除的特性

这里列出其它被删除的比较小的内容:

std::random_shuffle

此算法在 C++14 已被标记为弃用。原因是大多数的实现里都用到了 rand(),这个函数不够高效甚至容易出错(因为它用到了全局状态)。如果你需要同样的功能可以用:

1
2
template< class RandomIt, class URBG >
void shuffle( RandomIt first, RandomIt last, URBG&& g );

std::shuffle 接受一个随机数生成器作为第三个参数。更多参见 N4190

删除旧的 functional 相关

bind1st() / bind2st() / mem_fun() 等这些函数,在 C++98 时代被引入,现在已经不需要了,你可以用 lambda。更重要的是,这些函数没有更新以处理完美转发、decltype 以及其它 C++11 以来的现代化技术。因此最好不要在现代 C++ 里用它们。更多参见 N4190

删除三标符(trigraphs)

三标符是一种特殊的字符序列,在一些不支持 7-bit ASCII 码的系统(比如 ISO 646)上有用。比如 ??= 生成 #??- 代表 ~(所有 C++ 源代码字符集都包含在 7-bit ASCII 码中)。在今天三标符已经很少用到,把它从翻译阶段移除,编译处理会更直截了当。参见 N4086

译注:阅读本书之前,我完全不知道三标符的存在,只能勉强翻译。除上边草案外,还可以参考这里

评论