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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:03:12  来源:igfitidea点击:

What breaking changes are introduced in C++11?

c++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 autoas 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 terminatein C++0x, but does not in C++03. Because the implicit exception specification of A::~Ain C++0x is noexcept(true).

此代码terminate在 C++0x 中调用,但不在 C++03 中调用。因为A::~A在 C++0x 中的隐式异常规范是noexcept(true).



A valid C++ 2003 declaration containing exportis 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 #includesheaders 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 posixis now reserved for standardization.

全局命名空间posix现在保留用于标准化。



Valid C++ 2003 code that defines override, final, carries_dependency, or noreturnas macros is invalid in C++0x.

overridefinalcarries_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...

那么,对于一件事,如果你使用decltypeconstexprnullptr等作为标识符,那么你可能会遇到麻烦?

回答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 gboth 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>::fis not valid in C++0x, because name lookup when instantiating will find A<int>::fas 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::Bis still inaccessible in main.

上面的示例代码在 C++03 中格式良好,但在 C++0x 中格式错误,因为A::Bmain.

回答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 of val. This value is stored in valand ios_base::goodbitis stored in err.
  • The sequence of chars accumulated in stage 2 would have caused scanfto report an input failure. ios_base::failbitis assigned to err. [ed: Nothing is stored in val.]

[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::failbitis assigned to err.
  • the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbitis assigned to err.
  • 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::failbitis assigned to err.
  • the converted value, otherwise.

The resultant numeric value is stored in val.

[C++03: 22.2.2.1.2/11]:阶段 2 处理的结果可以是以下之一

  • 在第 2 阶段累积了一系列字符,该序列被转换(根据 的规则scanf)为 类型的值val。该值存储valios_base::goodbit存储在err.
  • 在第 2 阶段累积的字符序列会导致scanf报告输入失败。ios_base::failbit分配给err. [ed: 中没有存储任何内容val。]

[C++11: 22.4.2.1.2/3]:[..]要存储的数值可以是以下之一:

  • 零,如果转换函数无法转换整个字段ios_base::failbit分配给err.
  • 最正的可表示值,如果该字段表示的值太大而无法在 中表示valios_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*() constto explicit operator bool() constwill 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*() constto的变化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.

例如,考虑std::vector默认构造、C++0x 和破坏性更改

回答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

语言特点

  1. Uniform and general initialization using {}
  2. auto
  3. Prevention of narrowing
  4. constexpr
  5. Range based for loop
  6. nullptr
  7. enum class
  8. static_assert
  9. std::initializer_list
  10. Rvalue references (move semantics)
  11. >>
  12. Lambdas
  13. Variadic templates
  14. Type and template aliases
  15. Unicode characters
  16. long long integer type
  17. alignas and alignof
  18. decltype
  19. Raw string literals
  20. Generalized POD
  21. Generalized unions
  22. Local classes as template arguments
  23. Suffix return type syntax
  24. [[carries_dependency]] and [[noreturn]]
  25. noexcept specifier
  26. noexcept operator.
  27. C99 features:
    • extended integral types
    • concatenation of narrow/wide string
    • _ _ STDC_HOSTED _ _
    • _Pragma(X)
    • vararg macros and empty macro arguments
  28. _ _ func _ _
  29. Inline namespaces
  30. Delegating constructors
  31. In-class member initializers
  32. default and delete
  33. Explicit conversion operators
  34. User-defined literals
  35. Extern templates
  36. Default template arguments for function templates
  37. Inheriting constructors
  38. override and final
  39. Simpler and more general SFINAE rule
  40. Memory model
  41. thread_local
  1. 使用 {} 进行统一和一般初始化
  2. 汽车
  3. 防止变窄
  4. 常量表达式
  5. 基于范围的 for 循环
  6. 空指针
  7. 枚举类
  8. 静态断言
  9. std::initializer_list
  10. 右值引用(移动语义)
  11. >>
  12. 拉姆达
  13. 可变模板
  14. 类型和模板别名
  15. Unicode 字符
  16. 长整型
  17. alignas 和 alignof
  18. 声明类型
  19. 原始字符串文字
  20. 广义POD
  21. 广义工会
  22. 本地类作为模板参数
  23. 后缀返回类型语法
  24. [[carries_dependency]] 和 [[noreturn]]
  25. noexcept 说明符
  26. noexcept 运算符。
  27. C99特点:
    • 扩展整数类型
    • 窄/宽字符串的串联
    • _ _ STDC_HOSTED _ _
    • _Pragma(X)
    • vararg 宏和空宏参数
  28. _ _ 功能 _ _
  29. 内联命名空间
  30. 委托构造函数
  31. 类内成员初始值设定项
  32. 默认和删除
  33. 显式转换运算符
  34. 用户定义的文字
  35. 外部模板
  36. 函数模板的默认模板参数
  37. 继承构造函数
  38. 覆盖和最终
  39. 更简单、更通用的 SFINAE 规则
  40. 内存模型
  41. 线程本地

Standard-Library Components

标准库组件

  1. initializer_list for containers
  2. Move semantics for containers
  3. forward_list
  4. Hash containers
    • unordered_map
    • unordered_multimap
    • unordered_set
    • unordered_multiset
  5. Resource management pointers
    • unique_ptr
    • shared_ptr
    • weak_ptr
  6. Concurrency support
    • thread
    • mutexes
    • locks
    • condition variables
  7. Higher-level concurrency support
    • packaged_thread
    • future
    • promise
    • async
  8. tuples
  9. regex
  10. Random numbers
    • uniform_int_distribution
    • normal_distribution
    • random_engine
    • etc.
  11. Integer type names, such as int16_t , uint32_t , and int_fast64_t
  12. array
  13. Copying and rethrowing exceptions
  14. system_error
  15. emplace() operations for containers
  16. constexpr functions
  17. Systematic use of noexcept functions
  18. function and bind
  19. String to numeric value conversions
  20. Scoped allocators
  21. Type traits
  22. Time utilities: duration and time_point
  23. ratio
  24. quick_exit
  25. More algorithms, such as move() , copy_if() , and is_sorted()
  26. Garbage collection ABI
  27. atomics
  1. 容器的初始化列表
  2. 容器的移动语义
  3. forward_list
  4. 哈希容器
    • unordered_map
    • unordered_multimap
    • 无序集
    • unordered_multiset
  5. 资源管理指针
    • unique_ptr
    • shared_ptr
    • 弱指针
  6. 并发支持
    • 线
    • 互斥体
    • 条件变量
  7. 更高级别的并发支持
    • 打包线程
    • 未来
    • 承诺
    • 异步
  8. 元组
  9. 正则表达式
  10. 随机数
    • uniform_int_distribution
    • normal_distribution
    • 随机引擎
    • 等等。
  11. 整数类型名称,例如 int16_t 、 uint32_t 和 int_fast64_t
  12. 大批
  13. 复制和重新抛出异常
  14. 系统错误
  15. 容器的 emplace() 操作
  16. constexpr 函数
  17. noexcept 函数的系统使用
  18. 函数和绑定
  19. 字符串到数值的转换
  20. 范围分配器
  21. 类型特征
  22. 时间工具:duration 和 time_point
  23. 比率
  24. 快速退出
  25. 更多算法,例如 move() 、 copy_if() 和 is_sorted()
  26. 垃圾收集 ABI
  27. 原子

Deprecated Features

已弃用的功能

  1. Generation of the copy constructor and the copy assignment for a class with a destructor.
  2. Assign a string literal to a char *.
  3. C++98 exception specification
    • unexcepted_handler
    • set_unexpected
    • get_unexpected
    • unexpected
  4. Function objects and associated functions
  5. auto_ptr
  6. register
  7. ++ on a bool
  8. export
  9. C-style casts
  1. 为具有析构函数的类生成复制构造函数和复制赋值。
  2. 将字符串文字分配给 char *。
  3. C++98 异常规范
    • unexcepted_handler
    • 设置_意外
    • get_unexpected
    • 意外
  4. 函数对象和相关函数
  5. auto_ptr
  6. 登记
  7. ++ 在布尔值上
  8. 出口
  9. C 风格的强制转换