C++11 引入了哪些重大变化?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6399615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What breaking changes are introduced in C++11?
提问by R. Martinho Fernandes
I know that at least one of the changes in C++11 that will cause some old code to stop compiling: the introduction of explicit operator bool()
in the standard library, replacing old instances of operator void*()
. Granted, the code that this will break is probably code that should not have been valid in the first place, but it's still a breaking change nonetheless: programs that used to be valid no longer are.
我知道 C++11 中至少有一个变化会导致一些旧代码停止编译:explicit operator bool()
在标准库中引入,替换operator void*()
. 诚然,这将破坏的代码可能是一开始就不应该有效的代码,但它仍然是一个破坏性的变化:曾经有效的程序不再有效。
Are there any other breaking changes?
还有其他重大变化吗?
回答by Johannes Schaub - litb
The FDIS has a section for incompatibilities, at appendix C.2
"C++ and ISO C++ 2003".
FDIS 在附录C.2
“C++ 和 ISO C++ 2003”中有一个不兼容部分。
Summary, paraphrasing the FDIS here, to make it (better) suitable as a SO answer. I added some examples of my own to illustrate the differences.
总结,在此处解释 FDIS,使其(更好)适合作为 SO 答案。我添加了一些我自己的例子来说明差异。
There are a few library-related incompatibilities where I don't exactly know the implications of, so I leave those for others to elaborate on.
有一些与库相关的不兼容性,我不完全知道其含义,因此我将这些问题留给其他人详细说明。
Core language
核心语言
#define u8 "abc"
const char *s = u8"def"; // Previously "abcdef", now "def"
#define _x "there"
"hello"_x // now a user-defined-string-literal. Previously, expanded _x .
New keywords: alignas, alignof, char16_t, char32_t, constexpr, decltype, noexcept, nullptr, static_assert, and thread_local
新关键字:alignas、alignof、char16_t、char32_t、constexpr、decltype、noexcept、nullptr、static_assert 和 thread_local
Certain integer literals larger than can be represented by long could change from an unsigned integer type to signed long long.
某些大于 long 可以表示的整数文字可以从无符号整数类型更改为有符号 long long。
Valid C++ 2003 code that uses integer division rounds the result toward 0 or toward negative infinity, whereas C++0x always rounds the result toward 0.
使用整数除法的有效 C++ 2003 代码将结果向 0 或向负无穷大舍入,而 C++0x 始终将结果向 0 舍入。
(admittedly not really a compatibility problem for most people).
(诚然,对于大多数人来说,这并不是真正的兼容性问题)。
Valid C++ 2003 code that uses the keyword
auto
as a storage class specifier may be invalid in C++0x.
使用关键字
auto
作为存储类说明符的有效 C++ 2003 代码在 C++0x 中可能无效。
Narrowing conversions cause incompatibilities with C++03. For example, the following code is valid in C++ 2003 but invalid in this International Standard because double to int is a narrowing conversion:
缩小转换会导致与 C++03 不兼容。例如,以下代码在 C++ 2003 中有效,但在本国际标准中无效,因为 double 到 int 是一种收缩转换:
int x[] = { 2.0 };
Implicitly-declared special member functions are de?ned as deleted when the implicit definition would have been ill-formed.
A valid C++ 2003 program that uses one of these special member functions in a context where the definition is not required (e.g., in an expresion that is not potentially evaluated) becomes ill-formed.
当隐式定义格式错误时,隐式声明的特殊成员函数被定义为已删除。
一个有效的 C++ 2003 程序在不需要定义的上下文中使用这些特殊成员函数之一(例如,在没有潜在评估的表达式中)会变得格式错误。
Example by me:
我的例子:
struct A { private: A(); };
struct B : A { };
int main() { sizeof B(); /* valid in C++03, invalid in C++0x */ }
Such sizeof tricks have been used by some SFINAE, and needs to be changed now :)
一些SFINAE已经使用了这种sizeof技巧,现在需要更改:)
User-declared destructors have an implicit exception specification.
用户声明的析构函数具有隐式异常规范。
Example by me:
我的例子:
struct A {
~A() { throw "foo"; }
};
int main() { try { A a; } catch(...) { } }
This code calls terminate
in C++0x, but does not in C++03. Because the implicit exception specification of A::~A
in C++0x is noexcept(true)
.
此代码terminate
在 C++0x 中调用,但不在 C++03 中调用。因为A::~A
在 C++0x 中的隐式异常规范是noexcept(true)
.
A valid C++ 2003 declaration containing
export
is ill-formed in C++0x.
包含的有效 C++ 2003 声明
export
在 C++0x 中格式错误。
A valid C++ 2003 expression containing
>
followed immediately by another>
may now be treated as closing two templates.
现在可以将包含
>
紧接另一个的有效 C++ 2003 表达式>
视为关闭两个模板。
In C++03, >>
would always be the shift-operator token.
在 C++03 中,>>
将始终是移位运算符标记。
Allow dependent calls of functions with internal linkage.
允许依赖调用具有内部链接的函数。
Example by me:
我的例子:
static void f(int) { }
void f(long) { }
template<typename T>
void g(T t) { f(t); }
int main() { g(0); }
In C++03, this calls f(long)
, but in C++0x, this calls f(int)
. It should be noted that in both C++03 and C++0x, the following calls f(B)
(the instantiation context still only considers extern linkage declarations).
在 C++03 中,这调用f(long)
,但在 C++0x 中,这调用f(int)
. 需要注意的是,在C++03和C++0x中,以下调用f(B)
(实例化上下文仍然只考虑extern链接声明)。
struct B { };
struct A : B { };
template<typename T>
void g(T t) { f(t); }
static void f(A) { }
void f(B) { }
int main() { A a; g(a); }
The better matching f(A)
is not taken, because it does not have external linkage.
更好的匹配f(A)
不采取,因为它没有外部链接。
Library changes
图书馆变化
Valid C++ 2003 code that uses any identifiers added to the C++ standard library of C++0x may fail to compile or produce different results in This International Standard.
使用添加到 C++0x 的 C++ 标准库中的任何标识符的有效 C++ 2003 代码可能无法编译或在本国际标准中产生不同的结果。
Valid C++ 2003 code that
#includes
headers with names of new C++0x standard library headers may be invalid in this International Standard.
#includes
带有新 C++0x 标准库标头名称的标头的有效 C++ 2003 代码在本国际标准中可能无效。
Valid C++ 2003 code that has been compiled expecting swap to be in
<algorithm>
may have to instead include<utility>
已编译预期交换的有效 C++ 2003 代码
<algorithm>
可能必须改为包括<utility>
The global namespace
posix
is now reserved for standardization.
全局命名空间
posix
现在保留用于标准化。
Valid C++ 2003 code that defines
override
,final
,carries_dependency
, ornoreturn
as macros is invalid in C++0x.
将
override
、final
、carries_dependency
或定义noreturn
为宏的有效 C++ 2003 代码在 C++0x 中无效。
回答by arsenm
The meaning of the auto keyword changed.
auto 关键字的含义发生了变化。
回答by Downvoter
Breaking change?
突破性改变?
Well, for one thing, if you used decltype
, constexpr
, nullptr
, etc. as identifiers then you may be in trouble...
那么,对于一件事,如果你使用decltype
,constexpr
,nullptr
等作为标识符,那么你可能会遇到麻烦?
回答by Johannes Schaub - litb
Some core incompatibilities that are not covered by the incompatibilities section:
不兼容性部分未涵盖的一些核心不兼容性:
C++0x treats the injected class name as a template, if the name is passed as an argument to a template template parameter, and as a type if it is passed to a template type parameter.
C++0x 将注入的类名视为模板,如果该名称作为参数传递给模板模板参数,如果它作为类型传递给模板类型参数。
Valid C++03 code may behave differently if it relies on the injected class name to be always a type in these scenarios. Example code taken from my clang PR
如果在这些情况下,有效的 C++03 代码依赖于注入的类名始终是一种类型,则其行为可能会有所不同。从我的 clang PR 中获取的示例代码
template<template<typename> class X>
struct M { };
template<template<typename> class X>
void g(int = 0); // #1
template<typename T>
void g(long = 0); // #2
template<typename T>
struct A {
void f() {
g<A>(); /* is ambiguous in C++0x */
g<A>(1); /* should choose #1 in C++0x */
}
};
void h() {
A<int> a;
a.f();
}
In C++03, the code calls the second g
both times.
在 C++03 中,代码g
两次调用第二个。
C++0x makes some names that were dependent in C++03 to be now non-dependent. And requires name lookup for non-dependent qualified names that refer to members of the current class template to be repeated at instantiation, and requires verification that these names lookup the same way as done at the template definition context.
C++0x 使一些在 C++03 中依赖的名称现在是非依赖的。并且要求在实例化时重复引用当前类模板成员的非依赖限定名称的名称查找,并要求验证这些名称的查找方式与模板定义上下文中的查找方式相同。
Valid C++03 code that depends on the dominance rule may now not compile anymore because of this change.
由于此更改,依赖于支配规则的有效 C++03 代码现在可能不再编译。
Example:
例子:
struct B { void f(); };
template<typename T>
struct A : virtual B { void f(); };
template<typename T>
struct C : virtual B, A<T> {
void g() { this->f(); }
};
int main() { C<int> c; c.g(); }
This valid C++03 code that calls A<int>::f
is not valid in C++0x, because name lookup when instantiating will find A<int>::f
as opposed to B::f
, causing a conflict with the at-definition lookup.
调用的这个有效的 C++03 代码A<int>::f
在 C++0x 中是无效的,因为实例化时的名称查找会找到A<int>::f
与 相对的B::f
,从而导致与定义查找的冲突。
At this point, it is not clear whether that is a defect in the FDIS. The committee is aware of this and will evaluate the situation.
目前,尚不清楚这是否是 FDIS 中的缺陷。委员会意识到这一点,并将评估情况。
A using declaration where the last part is the same as the identifier in the last part of the qualifier in the qualified name denoting a base class, that using declaration now names the constructor, instead of members with that name.
一个 using 声明,其中最后一部分与表示基类的限定名称中限定符的最后一部分中的标识符相同,该 using 声明现在命名构造函数,而不是具有该名称的成员。
Example:
例子:
struct A { protected: int B; };
typedef A B;
struct C : B {
// inheriting constructor, instead of bringing A::B into scope
using B::B;
};
int main() { C c; c.B = 0; }
The above example code is well-formed in C++03, but ill-formed in C++0x, as A::B
is still inaccessible in main
.
上面的示例代码在 C++03 中格式良好,但在 C++0x 中格式错误,因为A::B
在main
.
回答by Lightness Races in Orbit
Stream extraction failure is treated differently.
流提取失败的处理方式不同。
Example
例子
#include <sstream>
#include <cassert>
int main()
{
std::stringstream ss;
ss << '!';
int x = -1;
assert(!(ss >> x)); // C++03 and C++11
assert(x == -1); // C++03
assert(x == 0); // C++11
}
Change proposal
变更提案
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3246.html#23
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3246.html#23
Standard reference
标准参考
[C++03: 22.2.2.1.2/11]:
The result of stage 2 processing can be one of
- A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of
scanf
) to a value of the type ofval
. This value is stored inval
andios_base::goodbit
is stored inerr
.- The sequence of chars accumulated in stage 2 would have caused
scanf
to report an input failure.ios_base::failbit
is assigned toerr
. [ed: Nothing is stored inval
.]
[C++11: 22.4.2.1.2/3]:
[..]The numeric value to be stored can be one of:
- zero, if the conversion function fails to convert the entire field.
ios_base::failbit
is assigned toerr
.- the most positive representable value, if the field represents a value too large positive to be represented in
val
.ios_base::failbit
is assigned toerr
.- the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in
val
.ios_base::failbit
is assigned toerr
.- the converted value, otherwise.
The resultant numeric value is stored in
val
.
[C++03: 22.2.2.1.2/11]:
阶段 2 处理的结果可以是以下之一
- 在第 2 阶段累积了一系列字符,该序列被转换(根据 的规则
scanf
)为 类型的值val
。该值存储val
并ios_base::goodbit
存储在err
.- 在第 2 阶段累积的字符序列会导致
scanf
报告输入失败。ios_base::failbit
分配给err
. [ed: 中没有存储任何内容val
。]
[C++11: 22.4.2.1.2/3]:
[..]要存储的数值可以是以下之一:
- 零,如果转换函数无法转换整个字段。
ios_base::failbit
分配给err
.- 最正的可表示值,如果该字段表示的值太大而无法在 中表示
val
。ios_base::failbit
分配给err
.- 如果该字段表示的值太大而无法在
val
.ios_base::failbit
分配给err
.- 转换后的值,否则。
结果数值存储在
val
.
Implementations
实现
GCC 4.8correctly outputs for C++11:
Assertion `x == -1' failed
GCC 4.5-4.8all output for C++03the following, which would appear to be a bug:
Assertion `x == -1' failed
Visual C++ 2008 Expresscorrectly outputs for C++03:
Assertion failed: x == 0
Visual C++ 2012 Expressincorrectly outputs for C++11, which would appear to be a status-of-implementation issue:
Assertion failed: x == 0
GCC 4.8为 C++11 正确输出:
断言 `x == -1' 失败
GCC 4.5-4.8 C++03的所有输出如下,这似乎是一个错误:
断言 `x == -1' 失败
Visual C++ 2008 Express为 C++03 正确输出:
断言失败:x == 0
Visual C++ 2012 Express错误地为 C++11 输出,这似乎是一个实现状态问题:
断言失败:x == 0
回答by Xeo
How is the introduction of explicit conversion operators a breaking change? The old version will still just be as "valid" as before.
显式转换运算符的引入是如何带来突破性变化的?旧版本仍然像以前一样“有效”。
Yes, the change from operator void*() const
to explicit operator bool() const
will be a breaking change, but only if it is used in a way that is wrong in and out of itself. Conforming code won't be broken.
是的,从operator void*() const
to的变化explicit operator bool() const
将是一个突破性的变化,但前提是它的使用方式本身是错误的。合规的代码不会被破坏。
Now, another breaking change is the banning of narrowing conversions during aggregate initialization:
现在,另一个重大变化是在聚合初始化期间禁止缩小转换:
int a[] = { 1.0 }; // error
Edit: Just rememberer, std::identity<T>
will be removed in C++0x(see the note). It's a convenience struct to make types dependent. Since the struct really doesn't do much, this should fix it:
编辑:只是记住,std::identity<T>
将在 C++0x 中删除(见注释)。这是一种使类型依赖的便利结构。由于结构确实没有做太多,这应该解决它:
template<class T>
struct identity{
typedef T type;
};
回答by James McNellis
There are numerous changes to the containers library that allow more efficient code but silently break backwards compatibility for a few corner cases.
容器库有许多更改,允许更高效的代码,但在一些极端情况下默默地破坏了向后兼容性。
Consider, for example, std::vector
, default construction, C++0x, and breaking changes.
回答by Ben Voigt
There's been a lot of discussion of implicit move breaking backward compatibility
有很多关于隐式移动破坏向后兼容性的讨论
(an older page with relevant discussion)
If you read down into the comments, implicit move return is also a breaking change.
如果你仔细阅读评论,隐式移动返回也是一个突破性的变化。
回答by Lightness Races in Orbit
struct x {
x(int) {}
};
void f(auto x = 3) { }
int main() {
f();
}
C++03:valid.
C++03:有效。
C++0x:error: parameter declared 'auto'
C++0x:error: parameter declared 'auto'
回答by mustafagonul
Language Features
语言特点
- Uniform and general initialization using {}
- auto
- Prevention of narrowing
- constexpr
- Range based for loop
- nullptr
- enum class
- static_assert
- std::initializer_list
- Rvalue references (move semantics)
>>
- Lambdas
- Variadic templates
- Type and template aliases
- Unicode characters
- long long integer type
- alignas and alignof
- decltype
- Raw string literals
- Generalized POD
- Generalized unions
- Local classes as template arguments
- Suffix return type syntax
- [[carries_dependency]] and [[noreturn]]
- noexcept specifier
- noexcept operator.
- C99 features:
- extended integral types
- concatenation of narrow/wide string
- _ _ STDC_HOSTED _ _
- _Pragma(X)
- vararg macros and empty macro arguments
- _ _ func _ _
- Inline namespaces
- Delegating constructors
- In-class member initializers
- default and delete
- Explicit conversion operators
- User-defined literals
- Extern templates
- Default template arguments for function templates
- Inheriting constructors
- override and final
- Simpler and more general SFINAE rule
- Memory model
- thread_local
- 使用 {} 进行统一和一般初始化
- 汽车
- 防止变窄
- 常量表达式
- 基于范围的 for 循环
- 空指针
- 枚举类
- 静态断言
- std::initializer_list
- 右值引用(移动语义)
>>
- 拉姆达
- 可变模板
- 类型和模板别名
- Unicode 字符
- 长整型
- alignas 和 alignof
- 声明类型
- 原始字符串文字
- 广义POD
- 广义工会
- 本地类作为模板参数
- 后缀返回类型语法
- [[carries_dependency]] 和 [[noreturn]]
- noexcept 说明符
- noexcept 运算符。
- C99特点:
- 扩展整数类型
- 窄/宽字符串的串联
- _ _ STDC_HOSTED _ _
- _Pragma(X)
- vararg 宏和空宏参数
- _ _ 功能 _ _
- 内联命名空间
- 委托构造函数
- 类内成员初始值设定项
- 默认和删除
- 显式转换运算符
- 用户定义的文字
- 外部模板
- 函数模板的默认模板参数
- 继承构造函数
- 覆盖和最终
- 更简单、更通用的 SFINAE 规则
- 内存模型
- 线程本地
Standard-Library Components
标准库组件
- initializer_list for containers
- Move semantics for containers
- forward_list
- Hash containers
- unordered_map
- unordered_multimap
- unordered_set
- unordered_multiset
- Resource management pointers
- unique_ptr
- shared_ptr
- weak_ptr
- Concurrency support
- thread
- mutexes
- locks
- condition variables
- Higher-level concurrency support
- packaged_thread
- future
- promise
- async
- tuples
- regex
- Random numbers
- uniform_int_distribution
- normal_distribution
- random_engine
- etc.
- Integer type names, such as int16_t , uint32_t , and int_fast64_t
- array
- Copying and rethrowing exceptions
- system_error
- emplace() operations for containers
- constexpr functions
- Systematic use of noexcept functions
- function and bind
- String to numeric value conversions
- Scoped allocators
- Type traits
- Time utilities: duration and time_point
- ratio
- quick_exit
- More algorithms, such as move() , copy_if() , and is_sorted()
- Garbage collection ABI
- atomics
- 容器的初始化列表
- 容器的移动语义
- forward_list
- 哈希容器
- unordered_map
- unordered_multimap
- 无序集
- unordered_multiset
- 资源管理指针
- unique_ptr
- shared_ptr
- 弱指针
- 并发支持
- 线
- 互斥体
- 锁
- 条件变量
- 更高级别的并发支持
- 打包线程
- 未来
- 承诺
- 异步
- 元组
- 正则表达式
- 随机数
- uniform_int_distribution
- normal_distribution
- 随机引擎
- 等等。
- 整数类型名称,例如 int16_t 、 uint32_t 和 int_fast64_t
- 大批
- 复制和重新抛出异常
- 系统错误
- 容器的 emplace() 操作
- constexpr 函数
- noexcept 函数的系统使用
- 函数和绑定
- 字符串到数值的转换
- 范围分配器
- 类型特征
- 时间工具:duration 和 time_point
- 比率
- 快速退出
- 更多算法,例如 move() 、 copy_if() 和 is_sorted()
- 垃圾收集 ABI
- 原子
Deprecated Features
已弃用的功能
- Generation of the copy constructor and the copy assignment for a class with a destructor.
- Assign a string literal to a char *.
- C++98 exception specification
- unexcepted_handler
- set_unexpected
- get_unexpected
- unexpected
- Function objects and associated functions
- auto_ptr
- register
- ++ on a bool
- export
- C-style casts
- 为具有析构函数的类生成复制构造函数和复制赋值。
- 将字符串文字分配给 char *。
- C++98 异常规范
- unexcepted_handler
- 设置_意外
- get_unexpected
- 意外
- 函数对象和相关函数
- auto_ptr
- 登记
- ++ 在布尔值上
- 出口
- C 风格的强制转换