在C++14中引入的更改可能会破坏用C++11编写的程序

What changes introduced in C++14 can potentially break a program written in C++11?

本文关键字:C++11 程序 C++14      更新时间:2023-10-16

简介

随着C++14(又名C++1y(标准接近最终版本,程序员必须自问向后兼容性以及与之相关的问题。


问题

在对该问题的回答中,指出本标准有一个附录,专门用于说明修订之间的变更信息。

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

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

注意:在这篇文章中,我认为断裂变化";属于或同时属于
CCD_ 1 1。当编译为C++14时,将使合法的C++11格式错误的更改,以及
CCD_ 2 2。当编译为C++14时,与C++11相比,将更改运行时行为的更改


C++11与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(

有关此功能的潜在问题是,单引号C++11中总是表示字符文字的开始/结束,但在C++14单引号可以围绕字符文字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

关于潜在问题的进一步信息:

重新定义全局无大小版本的现有程序也不会定义大小版本。当实现引入大小版本,替换将不完整,很可能程序将调用上提供大小的解除定位器的实现用程序员提供的分配器分配的对象。

注意:报价取自n3536-C++规模的经销商

(注:更多感兴趣的内容可在题为n3536-C++规模的交易,作者Lawrence Crowl(


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

在C++14中,constexpr有很多变化,但唯一会改变C++11C++14之间语义的变化是标记为constexpr成员函数的constants

这一更改背后的基本原理是允许constexpr成员函数对其所属的对象进行变异,这是由于constexpr的放宽而允许的。

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

关于这一变化的推荐材料,以及为什么它足够重要,可以引入潜在的代码破坏:

  • Andrzej的C++博客-"constexpr"函数不是"const">
  • open-std.org.-constexpr成员函数和隐式const
  • (open-std.org/strong>-放宽对constexpr函数的约束(

示例代码段,在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已从标准库中删除,因为它被认为是危险的。

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


(注意:有一些编写代码的方法不会编译失败,并且具有不同的行为,这取决于从标准库中删除std::gets(