Yes, there are number of changes that will cause the same code to result in different behavior between C++03 and C++11. The sequencing rules differences make for some interesting changes including some previously undefined behavior becoming well defined.

1. multiple mutations of the same variable within an initializer list

One very interesting corner case would multiple mutations of the same variable within an initializer list, for example:

int main() { int count = 0 ; int arrInt[2] = { count++, count++ } ; return 0 ; }

In both C++03 and C++11 this is well defined but the order of evaluation in C++03 is unspecified but in C++11 they are evaluated in the order in which they appear. So if we compile using clang in C++03 mode it provide the following warning (see it live):

warning: multiple unsequenced modifications to 'count' [-Wunsequenced] int arrInt[2] = { count++, count++ } ; ^ ~~

but does not provide a warning in C++11 (see it live).

2. New sequencing rules make i = ++ i + 1; well defined in C++11

The new sequencing rules adopted after C++03 means that:

int i = 0 ; i = ++ i + 1;

is no longer undefined behavior in C++11, this is covered in defect report 637. Sequencing rules and example disagree

3. New sequencing rules also make ++++i ; well defined in C++11

The new sequencing rules adopted after C++03 means that:

int i = 0 ; ++++i ;

is no longer undefined behavior in C++11.

4. Slightly More Sensible Signed Left-Shifts

Later drafts of C++11 include N3485 which I link below fixed the undefined behavior of shifting a 1 bit into or past the sign bit. This is also covered in defect report 1457. Howard Hinnant commented on the significance of this change in the thread on Is left-shifting (<<) a negative integer undefined behavior in C++11?.

5. constexpr functions can be treated as compile time constant expressions in C++11

C++11 introduced constexpr functions which:

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed.

while C++03 does not have the constexpr feature we don't have to explicitly use the constexpr keyword since the standard library provides many functions in C++11 as constexpr. For example std::numeric_limits::min. Which can lead to different behavior, for example:

#include <limits> int main() { int x[std::numeric_limits<unsigned int>::min()+2] ; }

Using clang in C++03 this will cause x to be a variable length array, which is an extension and will generate the following warning:

warning: variable length arrays are a C99 feature [-Wvla-extension] int x[std::numeric_limits<unsigned int>::min()+2] ; ^

while in C++11 std::numeric_limits<unsigned int>::min()+2 is a compile time constant expression and does not require the VLA extension.

6. In C++11 noexcept exception specifications are implicitly generated for your destructors

Since in C++11 user defined destructor has implicit noexcept(true) specification as explained in noexcept destructors it means that the following program:

#include <iostream> #include <stdexcept> struct S { ~S() { throw std::runtime_error(""); } // bad, but acceptable }; int main() { try { S s; } catch (...) { std::cerr << "exception occurred"; } std::cout << "success"; }

In C++11 will call std::terminate but will run successfully in C++03.

7. In C++03, template arguments could not have internal linkage

This is covered nicely in Why std::sort doesn't accept Compare classes declared within a function. So the following code should not work in C++03:

#include <iostream> #include <vector> #include <algorithm> class Comparators { public: bool operator()(int first, int second) { return first < second; } }; int main() { class ComparatorsInner : public Comparators{}; std::vector<int> compares ; compares.push_back(20) ; compares.push_back(10) ; compares.push_back(30) ; ComparatorsInner comparatorInner; std::sort(compares.begin(), compares.end(), comparatorInner); std::vector<int>::iterator it; for(it = compares.begin(); it != compares.end(); ++it) { std::cout << (*it) << std::endl; } }

but currently clang allows this code in C++03 mode with a warning unless you use -pedantic-errors flag, which is kind of icky, see it live.

8. >> is not longer ill-formed when closing multiple templates

Using >> to close multiple templates is no longer ill-formed but can lead to code with different results in C++03 and C+11. The example below is taken from Right angle brackets and backwards compatibility:

#include <iostream> template<int I> struct X { static int const c = 2; }; template<> struct X<0> { typedef int c; }; template<typename T> struct Y { static int const c = 3; }; static int const c = 4; int main() { std::cout << (Y<X<1> >::c >::c>::c) << '

'; std::cout << (Y<X< 1>>::c >::c>::c) << '

'; }

and the result in C++03 is:

0 3

and in C++11:

0 0

9. C++11 changes some of std::vector constructors

Slightly modified code from this answer shows that using the following constructor from std::vector:

std::vector<T> test(1);

produces different results in C++03 and C++11:

#include <iostream> #include <vector> struct T { bool flag; T() : flag(false) {} T(const T&) : flag(true) {} }; int main() { std::vector<T> test(1); bool is_cpp11 = !test[0].flag; std::cout << is_cpp11 << std::endl ; }

10. Narrowing conversions in aggregate initializers

In C++11 a narrowing conversion in aggregate initializers is ill-formed and it looks like gcc allows this in both C++11 and C++03 although it provide a warning by default in C++11:

int x[] = { 2.0 };

This is covered in the draft C++11 standard section 8.5.4 List-initialization paragraph 3:

List-initialization of an object or reference of type T is defined as follows:

and contains the following bullet (emphasis mine):

Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed

This and many more instance are covered in the draft C++ standard section annex C.2 C++ and ISO C++ 2003. It also includes: