简介
随着 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++11 和 C++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中是不可能的。
但是,该标准还要求开发人员不能只声明以下两个相关函数之一,它必须声明 none 或 both;这在 [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++11 和 C++ 之间语义的变化14 是标记为 constexpr 的 member-function 的 constantness。
此更改背后的基本原理是允许 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 ,以及为什么引入潜在的代码破坏如此重要:
- Andrzej's C++ blog - “constexpr” function is not “const”
- open-std.org - constexpr member functions and implicit const
- (open-std.org - Relaxing constraints on constexpr functions)
示例片段,在 C++11 和 C++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/