我知道c++ 11中至少有一个变化会导致一些旧代码停止编译:在标准库中引入显式操作符bool(),取代操作符void*()的旧实例。当然,这将破坏的代码可能是本来就不应该有效的代码,但它仍然是一个破坏性的更改:过去有效的程序不再有效。

还有其他重大变化吗?


当前回答

auto关键字的含义改变。

其他回答

FDIS有一个关于不兼容性的章节,在附录C.2“c++和ISO c++ 2003”。

总结一下,这里对FDIS进行解释,使其(更好地)适合作为SO答案。我添加了一些我自己的例子来说明差异。

有一些与库相关的不兼容性,我不太清楚它们的含义,所以我把它们留给其他人来详细说明。

核心语言


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

新的关键字:alignas、alignof、char16_t、char32_t、constexpr、decltype、noexcept、nullptr、static_assert和thread_local


某些大于long可以表示的整数字面值可以从无符号整数类型变为有符号long long类型。


有效的c++ 2003代码使用整数除法将结果舍入到0或负无穷,而c++ 0x总是将结果舍入到0。

(诚然,对大多数人来说,这并不是一个兼容性问题)。


使用关键字auto作为存储类说明符的有效c++ 2003代码在c++ 0x中可能无效。


缩小转换会导致与c++ 03不兼容。例如,以下代码在c++ 2003中有效,但在本国际标准中无效,因为double到int是一种窄化转换:

int x[] = { 2.0 };

隐式声明的特殊成员函数在隐式定义格式错误时被定义为删除。 一个有效的c++ 2003程序如果在不需要定义的上下文中(例如,在一个没有潜在求值的表达式中)使用了这些特殊成员函数之一,就会变成病态形式。

我举的例子:

struct A { private: A(); };
struct B : A { };
int main() { sizeof B(); /* valid in C++03, invalid in C++0x */ }

一些SFINAE使用了这种尺寸的技巧,现在需要改变:)


用户声明的析构函数具有隐式异常规范。

我举的例子:

struct A {
  ~A() { throw "foo"; }
};

int main() { try { A a; } catch(...) { } }

这段代码在c++ 0x中调用terminate,但在c++ 03中没有。因为c++ 0x中A::~A的隐式异常规范是noexcept(true)。


包含export的有效c++ 2003声明在c++ 0x中是格式错误的。


一个有效的c++ 2003表达式包含>,后面紧跟着另一个>,现在可以被视为关闭两个模板。

在c++ 03中,>>将始终是shift运算符令牌。


允许具有内部链接的函数的依赖调用。

我举的例子:

static void f(int) { }
void f(long) { }

template<typename T>
void g(T t) { f(t); }

int main() { g(0); }

在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); }

不取匹配较好的f(A),因为它没有外部联系。


图书馆改变

使用添加到c++标准中的任何标识符的有效c++ 2003代码 c++ 0x的库可能无法编译或在本标准中产生不同的结果。


包含新c++ 0x标准库标头名称的有效c++ 2003代码在本标准中可能无效。


已编译的期望交换在<算法>中的有效c++ 2003代码可能必须包含<实用程序>


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


将override、final、carries_dependency或noreturn定义为宏的有效c++ 2003代码在c++ 0x中无效。

对容器库进行了大量更改,可以实现更高效的代码,但在一些极端情况下会默默地破坏向后兼容性。

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

struct x {
   x(int) {}
};

void f(auto x = 3) { }

int main() {
   f();
}

C++03:有效。

c++ 0x:错误:参数声明为auto

显式转换运算符的引入如何成为突破性的变化?旧版本仍然和以前一样“有效”。

是的,从操作符void*() const到显式操作符bool() const的变化将是一个破坏性的变化,但前提是它的使用方式内外都是错误的。符合规范的代码不会被打破。

现在,另一个突破性的变化是在聚合初始化期间禁止收缩转换:

int a[] = { 1.0 }; // error

编辑:请记住,std::identity<T>将在c++ 0x中被删除(参见注释)。它是一种方便的结构体,可以使类型相互依赖。由于结构体实际上并没有做太多的事情,这应该可以修复它:

template<class T>
struct identity{
  typedef T type;
};

流提取失败的处理方式不同。

例子

#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 of val. This value is stored in val and ios_base::goodbit is stored in err. The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure. ios_base::failbit is 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::failbit is assigned to err. the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is 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::failbit is assigned to err. the converted value, otherwise. The resultant numeric value is stored in val.

实现

GCC 4.8为c++ 11正确输出: 断言' x == -1'失败 GCC 4.5-4.8所有c++ 03的输出如下,这似乎是一个bug: 断言' x == -1'失败 Visual c++ 2008 Express正确输出c++ 03: 断言失败:x == 0 Visual c++ 2012 Express错误地输出了c++ 11,这似乎是一个实现状态问题: 断言失败:x == 0