c++ - C++14 中引入的哪些更改可能会破坏用 C++11 编写的程序?

标签 c++ c++11 c++14 language-lawyer c++-faq

简介

随着 C++14(又名。C++1y)标准接近最终版,程序员必须自问向后兼容性和问题与此类有关。


问题

this question 的回答中据说该标准有一个附录专门用于提供有关修订之间更改的信息。

如果可以解释前面提到的附录中的这些潜在问题,或许可以借助与其中提到的内容相关的任何正式文件来解释,这将是有帮助的。

  • 根据标准:C++14 中引入的哪些更改可能会破坏用 C++11 编写的程序?

最佳答案

Note: In this post I consider a "breaking change" to be either, or both, of;
1. a change that will make legal C++11 ill-formed when compiled as C++14, and;
2. a change that will change the runtime behavior when compiled as C++14, vs C++11.


C++11 vs C++14,标准怎么说?

标准草案 (n3797) 有一个专门用于此类信息的部分,其中描述了一个标准修订版与另一个修订版之间的(可能是重大的)差异。

这篇文章使用了该部分,[diff.cpp11] ,作为半详细讨论的基础,讨论可能会影响为 C++11 编写但编译为 C++14 的代码的更改。


C.3.1] 数字分隔符

引入了数字分隔符,以便人们可以以更易读的方式编写数字文字并以更自然的方式将它们拆分。

int x = 10000000;   // (1)
int y = 10'000'000; // (2), C++14

很容易看出 (2) 比上面代码片段中的 (1) 更容易阅读,而两个初始化器具有相同的值。

关于此功能的潜在问题是 单引号C++11 中总是表示 character-literal 的开始/结束em>,但在 C++14 中,单引号 可以围绕 character-literal,或者以前面所示的方式使用(2).


示例代码段,在 C++11C++14 中均合法,但行为不同。

#define M(x, ...) __VA_ARGS__

int a[] = { M(1'2, 3'4, 5) };

// int a[] = { 5 };        <-- C++11
// int a[] = { 3'4, 5 };   <-- C++14
//                              ^-- semantically equivalent to `{ 34, 5 }`

(注意:关于单引号作为数字分隔符的更多信息可以在n3781.pdf中找到)


C.3.2] 大小重新分配

C++14 引入了声明 operator delete 的全局重载的机会适合大小的释放,这在C++11中是不可能的。

但是,该标准还要求开发人员不能只声明以下两个相关函数之一,它必须声明 noneboth;这在 [new.delete.single]p11.

中有说明
void operator delete (void*) noexcept;
void operator delete (void*, std::size_t) noexcept; // sized deallocation


有关潜在问题的更多信息:

Existing programs that redefine the global unsized version do not also define the sized version. When an implementation introduces a sized version, the replacement would be incomplete and it is likely that programs would call the implementation-provided sized deallocator on objects allocated with the programmer-provided allocator.

Note: Quote taken from n3536 - C++ Sized Deallocation

(注意:更多感兴趣的文章请参阅由 Lawrence Crowl 撰写的标题为 n3536 - C++ Sized Deallocation 的论文)


C.3.3] constexpr成员函数,不再隐含 const

constexpr 在 C++14 中有很多变化,但唯一会改变 C++11C++ 之间语义的变化14 是标记为 constexprmember-functionconstantness

此更改背后的基本原理是允许 constexpr member-functions 改变它们所属的对象,这是由于 relaxation of constexpr 而允许的。 .

struct A { constexpr int func (); };

// struct A { constexpr int func () const; }; <-- C++11
// struct A { constexpr int func ();       }; <-- C++14


关于此更改的推荐 Material ,以及为什么引入潜在的代码破坏如此重要:


示例片段,在 C++11C++14 中均合法,但行为不同

struct Obj {
  constexpr int func (int) {
    return 1;
  }

  constexpr int func (float) const {
    return 2;
  }
};

Obj const a = {}; 
int const x = a.func (123);

// int const x = 1;   <-- C++11
// int const x = 2;   <-- C++14

C.3.4] 删除 std::gets

std::gets removed来自标准库,因为它是 considered dangerous .

当然,这意味着尝试在 C++14 中编译为 C++11 编写的代码,其中使用了这样的函数很可能无法编译。


(注意:有写入 code 的方法不会编译失败,并且具有不同的行为,这取决于从 标准库 中删除 std::gets) p>

关于c++ - C++14 中引入的哪些更改可能会破坏用 C++11 编写的程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23980929/

相关文章:

c++ - 函数调用优先级的重载和模板特化

c++ - 转发声明映射的映射类型和 C++11

c++ - vector 迭代器不可解引用

c++ - C++11 中的 lambda 表达式是什么?

c++ - 根据模板参数内容执行或跳过代码

c++ - 无法使用 std::map::emplace 插入没有复制构造函数的类的对象

c++ - 为什么我不能 range-for 遍历任意内容的初始化列表?

c++ - 使用链接列表制作复制构造函数

c# - 您如何向 C#/Java 开发人员解释 C++ 指针?

c++ - 带有可变参数的模板函数编译问题