What breaking changes are introduced in C++11?
我知道C++ 11中至少有一个改变会导致一些旧代码停止编译:在标准库中引入EDCOX1 OR 0,替换EDCOX1 1的旧实例。当然,这将破坏的代码可能是一开始就不应该有效的代码,但是它仍然是一个破坏性的变化:以前有效的程序不再是。
还有其他突破性的变化吗?
FDIS有一个不兼容的部分,在附录EDCOX1,8,"C++和ISO C++ 2003"。
总结一下,在这里解释外国直接投资,使之(更好)适合作为一个这样的答案。我添加了一些自己的例子来说明不同之处。
有一些与库相关的不兼容性,我不清楚它的含义,所以我将这些留给其他人详细说明。
核心语言1 2 | #define u8"abc" const char *s = u8"def"; // Previously"abcdef", now"def" |
1 2 | #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
Certain integer literals larger than can be represented by long could change from an unsigned integer type to signed 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.
(诚然,对于大多数人来说,这并不是一个真正的兼容性问题)。
Valid C++ 2003 code that uses the keyword
auto as a storage class specifier may be invalid in 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:
1 | 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.
我的例子:
1 2 3 | struct A { private: A(); }; struct B : A { }; int main() { sizeof B(); /* valid in C++03, invalid in C++0x */ } |
这种规模的技巧已经被一些sfinae使用,现在需要更改:)
User-declared destructors have an implicit exception specification.
我的例子:
1 2 3 4 5 | struct A { ~A() { throw"foo"; } }; int main() { try { A a; } catch(...) { } } |
此代码在C++ 0x中调用EDCOX1×9Ω,但不在C++ 03中调用。因为在C++ 0x中EDOCX1·10的隐含隐式规范是
A valid C++ 2003 declaration containing
export is ill-formed in C++0x.
A valid C++ 2003 expression containing
> followed immediately by another> may now be treated as closing two templates.
在C++ 03中,EDCOX1×12的总是将是移位操作符令牌。
Allow dependent calls of functions with internal linkage.
我的例子:
1 2 3 4 5 6 7 | static void f(int) { } void f(long) { } template<typename T> void g(T t) { f(t); } int main() { g(0); } |
在C++ 03中,它调用EDCOX1 OR 13,但是在C++ 0x中,它调用EDCOX1×14Ω。应该注意的是,在C++ 03和C++ 0x中,下面调用EDCOX1(15):(实例化上下文仍然只考虑外部链接声明)。
1 2 3 4 5 6 7 8 9 10 | 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); } |
由于没有外部链接,因此没有采用更好的匹配
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.
Valid C++ 2003 code that
#includes headers with names of new C++0x standard library headers may be invalid in this International Standard.
Valid C++ 2003 code that has been compiled expecting swap to be in
may have to instead include
The global namespace
posix is now reserved for standardization.
Valid C++ 2003 code that defines
override ,final ,carries_dependency , ornoreturn as macros is invalid in C++0x.
自动关键字的含义已更改。
打破改变?
嗯,首先,如果你用
不兼容部分未涵盖的一些核心不兼容:
C++0x将注入的类名视为模板,如果将该名称作为参数传递给模板模板参数,并将其传递给模板类型参数。
如果依赖于注入的类名在这些场景中始终是一个类型,则有效C++ 03代码的行为可能会有所不同。示例代码取自我的clang pr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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(); } |
在C++ 03中,代码调用第二个EDCOX1,0,这两个时间。
C++0X使一些依赖于C++ 03的名称现在不再依赖。并且需要对引用当前类模板成员的非依赖限定名进行名称查找,以便在实例化时重复,并且需要验证这些名称查找方式是否与在模板定义上下文中执行的方式相同。
依赖于支配规则的有效C++ 03代码现在不能再编译了,因为这个改变。
例子:
1 2 3 4 5 6 7 8 9 10 11 | 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(); } |
在C++ 0x中调用EDCOX1 OR 1的有效C++ 03代码无效,因为实例化时的名称查找会发现EDCOX1 1Ω,而不是EDCOX1 3Ω,导致AT定义查找冲突。
目前还不清楚这是否是外国直接投资的缺陷。委员会意识到这一点,并将对形势进行评估。
一个using声明,其中最后一部分与表示基类的限定名中限定符最后一部分中的标识符相同,该using声明现在命名构造函数,而不是具有该名称的成员。
例子:
1 2 3 4 5 6 7 8 9 | 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; } |
上面的示例代码在C++ 03中是很好的,但是在C++ 0x中是不正确的,因为EDCOX1,4,在EDCOX1 5中仍然是不可访问的。
流提取失败的处理方式不同。
例子1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #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 } |
更改建议
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3246.html_23
标准参考
[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 .
启动位置
GCC 4.8正确输出C++ 11:
Assertion `x == -1' failed
GCC 4.5-4.8所有输出的C++ 03如下,这似乎是一个错误:
Assertion `x == -1' failed
Visual C++ 2008表示C++ 03的正确输出:
Assertion failed: x == 0
Visual C++ 2012对C++ 11的输出表示不正确,这似乎是实现问题的一个状态:
Assertion failed: x == 0
显式转换运算符的引入是如何一种突破性的变化?旧版本仍将像以前一样"有效"。
是的,从
现在,另一个突破性的变化是在聚合初始化期间禁止收缩转换:
1 | int a[] = { 1.0 }; // error |
编辑:仅记住,EDCOX1,2将在C++0x中删除(见注释)。它是一个使类型依赖的便利结构。由于结构实际上不起多大作用,因此应该修复它:
1 2 3 4 | template<class T> struct identity{ typedef T type; }; |
对容器库进行了许多更改,这些更改允许更高效的代码,但会悄悄地破坏一些角情况的向后兼容性。
例如,考虑EDCOX1,7,默认构造,C++0x,和断裂变化。
关于隐式移动打破向后兼容性的讨论很多。
(有相关讨论的旧页)
如果您向下阅读注释,隐式移动返回也是一个突破性的更改。
1 2 3 4 5 6 7 8 9 | struct x { x(int) {} }; void f(auto x = 3) { } int main() { f(); } |
C++ 03:有效。
C++0x:EDCOX1〔6〕
语言功能
- 扩展积分类型
- 窄/宽字符串的串联
- _托管的stdc___
- λ(x)
- vararg宏和空宏参数
标准库组件
- 无序映射
- 无序的多重映射
- 乱序集
- 无序多集
- 尤尼奎
- SelddPPTR
- 弱者PTR
- 线
- 互斥器
- 锁
- 条件变量
- 打包螺纹
- 未来
- 承诺
- 异步的
- 均匀分布
- 正态分布
- 随机引擎
- 等。
不推荐使用的功能
- 无例外处理程序
- 意外出局
- 意想不到的
- 想不到的