本文翻译自:Can C++ code be valid in both C++03 and C++11 but do different things?
C ++代码是否可以符合C ++ 03标准和C ++ 11标准,但根据编译的标准,可以做不同的事情吗?
#1楼
参考:https://stackoom.com/question/1Yhd0/C-代码可以在C-和C-中有效但是做不同的事情吗
#2楼
I point you to this article and the follow-up , which has a nice example of how >> can change meaning from C++03 to C++11 while still compiling in both. 我点你这篇文章和随访 ,其中有如何一个很好的例子>>可以改变从C ++ 03意为C ++ 11,而在静止编制。
bool const one = true;
int const two = 2;
int const three = 3;
template<int> struct fun {
typedef int two;
};
template<class T> struct fon {
static int const three = ::three;
static bool const one = ::one;
};
int main(void) {
fon< fun< 1 >>::three >::two >::one; // valid for both
}
The key part is the line in main , which is an expression. 关键部分是main的一行,它是一个表达式。
In C++03: 在C ++ 03中:
1 >> ::three = 0
=> fon< fun< 0 >::two >::one;
fun< 0 >::two = int
=> fon< int >::one
fon< int >::one = true
=> true
In C++11 在C ++ 11中
fun< 1 > is a type argument to fon
fon< fun<1> >::three = 3
=> 3 > ::two > ::one
::two is 2 and ::one is 1
=> 3 > 2 > 1
=> (3 > 2) > 1
=> true > 1
=> 1 > 1
=> false
Congratulations, two different results for the same expression. 恭喜,同一表达的两个不同结果。 Granted, the C++03 one did come up with a warning form Clang when I tested it. 当然,在我测试它时,C ++ 03确实提出了警告形式Clang。
#3楼
The answer is a definite yes. 答案肯定是肯定的。 On the plus side there is: 从好的方面来说,有:
- Code that previously implicitly copied objects will now implicitly move them when possible. 以前隐式复制对象的代码现在将隐式移动它们。
On the negative side, several examples are listed in the appendix C of the standard. 从消极方面来看,标准的附录C中列出了几个例子。 Even though there are many more negative ones than positive, each one of them is much less likely to occur. 即使有更多的负面因素而不是正面,每一个都不太可能发生。
String literals 字符串文字
#define u8 "abc"
const char* s = u8"def"; // Previously "abcdef", now "def"
and 和
#define _x "there"
"hello "_x // Previously "hello there", now a user defined string literal
Type conversions of 0 输入0的转化次数
In C++11, only literals are integer null pointer constants: 在C ++ 11中,只有文字是整数空指针常量:
void f(void *); // #1
void f(...); // #2
template<int N> void g() {
f(0*N); // Calls #2; used to call #1
}
Rounded results after integer division and modulo 整数除法和模数后的舍入结果
In C++03 the compiler was allowed to either round towards 0 or towards negative infinity. 在C ++ 03中,允许编译器向0或向负无穷大舍入。 In C++11 it is mandatory to round towards 0 在C ++ 11中,必须向0舍入
int i = (-1) / 2; // Might have been -1 in C++03, is now ensured to be 0
Whitespaces between nested template closing braces >> vs > > 嵌套模板关闭括号>> vs >>之间的空格
Inside an specialization or instantiation the >> might instead be interpreted as an right-shift in C++03. 在专门化或实例化中, >>可能会被解释为C ++ 03中的右移。 This is more likely to break existing code though: (from http://gustedt.wordpress.com/2013/12/15/a-disimprovement-observed-from-the-outside-right-angle-brackets/ ) 这更有可能破坏现有代码:(来自http://gustedt.wordpress.com/2013/12/15/a-disimprovement-observed-from-the-outside-right-angle-brackets/ )
template< unsigned len > unsigned int fun(unsigned int x);
typedef unsigned int (*fun_t)(unsigned int);
template< fun_t f > unsigned int fon(unsigned int x);
void total(void) {
// fon<fun<9> >(1) >> 2 in both standards
unsigned int A = fon< fun< 9 > >(1) >>(2);
// fon<fun<4> >(2) in C++03
// Compile time error in C++11
unsigned int B = fon< fun< 9 >>(1) > >(2);
}
Operator new may now throw other exceptions than std::bad_alloc operator new现在可能抛出除std::bad_alloc之外的其他异常
struct foo { void *operator new(size_t x){ throw std::exception(); } }
try {
foo *f = new foo();
} catch (std::bad_alloc &) {
// c++03 code
} catch (std::exception &) {
// c++11 code
}
User-declared destructors have an implicit exception specification example from What breaking changes are introduced in C++11? 用户声明的析构函数有一个隐式异常规范示例来自C ++ 11中引入了哪些重大更改?
struct A {
~A() { throw "foo"; } // Calls std::terminate in C++11
};
//...
try {
A a;
} catch(...) {
// C++03 will catch the exception
}
size() of containers is now required to run in O(1) 容器的size()现在需要在O(1)中运行
std::list<double> list;
// ...
size_t s = list.size(); // Might be an O(n) operation in C++03
std::ios_base::failure does not derive directly from std::exception anymore std::ios_base::failure不再直接从std::exception派生
While the direct base-class is new, std::runtime_error is not. 虽然直接基类是新的,但std::runtime_error不是。 Thus: 从而:
try {
std::cin >> variable; // exceptions enabled, and error here
} catch(std::runtime_error &) {
std::cerr << "C++11\n";
} catch(std::ios_base::failure &) {
std::cerr << "Pre-C++11\n";
}
#4楼
One potentially dangerous backward-incompatible change is in constructors of sequence containers such as std::vector , specifically in the overload specifying initial size. 一个潜在危险的向后不兼容的变化是序列容器的构造函数,例如std::vector ,特别是在指定初始大小的重载中。 Where in C++03, they copied a default-constructed element, in C++11 they default-construct each one. 在C ++ 03中,他们复制了一个默认构造的元素,在C ++ 11中,他们默认构造每个元素。
Consider this example (using boost::shared_ptr so that it's valid C++03): 考虑这个例子(使用boost::shared_ptr这样它就是有效的C ++ 03):
#include <deque>
#include <iostream>
#include "boost/shared_ptr.hpp"
struct Widget
{
boost::shared_ptr<int> p;
Widget() : p(new int(42)) {}
};
int main()
{
std::deque<Widget> d(10);
for (size_t i = 0; i < d.size(); ++i)
std::cout << "d[" << i << "] : " << d[i].p.use_count() << '\n';
}
C++11 Live example C ++ 11 Live示例
The reason is that C++03 specified one overload for both "specify size and prototype element" and "specify size only," like this (allocator arguments omitted for brevity): 原因是C ++ 03为“指定大小和原型元素”和“仅指定大小”指定了一个重载,就像这样(为简洁省略了allocator参数):
container(size_type size, const value_type &prototype = value_type());
This will always copy prototype into the container size times. 这将始终将prototype复制到容器size时间。 When called with just one argument, it will therefore create size copies of a default-constructed element. 当使用一个参数调用时,它将创建默认构造元素的size副本。
In C++11, this constructor signature was removed and replaced with these two overloads: 在C ++ 11中,删除了此构造函数签名并替换为这两个重载:
container(size_type size);
container(size_type size, const value_type &prototype);
The second one works as before, creating size copies of the prototype element. 第二个像以前一样工作,创建prototype元素的size副本。 However, the first one (which now handles calls with only the size argument specified) default-constructs each element individually. 但是,第一个(现在只处理指定了size参数的调用)默认构造每个元素。
My guess for the reason of this change is that the C++03 overload wouldn't be usable with a move-only element type. 我猜测这种变化的原因是C ++ 03重载不适用于只移动元素类型。 But it's a breaking change none the less, and one seldom documented at that. 但它仍然是一个突破性的变化,而且很少有人记录在案。
#5楼
The result of a failed read from an std::istream has changed. 从std::istream读取失败的结果已更改。 CppReference summarizes it nicely: CppReference很好地总结了它:
If extraction fails (eg if a letter was entered where a digit is expected),
valueis left unmodified andfailbitis set. 如果提取失败(例如,如果输入了预期数字的字母),则value保持failbit并设置failbit。 (until C++11) (直到C ++ 11)If extraction fails, zero is written to
valueandfailbitis set. 如果提取失败,则将零写入value并设置failbit。 If extraction results in the value too large or too small to fit invalue,std::numeric_limits<T>::max()orstd::numeric_limits<T>::min()is written andfailbitflag is set. 如果提取结果的值太大或太小std::numeric_limits<T>::max()适合value,则写入std::numeric_limits<T>::max()或std::numeric_limits<T>::min()并设置failbit标志。 (since C++11) (自C ++ 11以来)
This is primarily an issue if you are used to the new semantics and then have to write using C++03. 如果您习惯于新语义然后必须使用C ++ 03编写,那么这主要是一个问题。 The following is not particularly good practice but well-defined in C++11: 以下不是特别好的做法,但在C ++ 11中定义良好:
int x, y;
std::cin >> x >> y;
std::cout << x + y;
However, in C++03, the above code uses an uninitialized variable and thus has undefined behaviour. 但是,在C ++ 03中,上面的代码使用了未初始化的变量,因此具有未定义的行为。
#6楼
This thread What differences, if any, between C++03 and C++0x can be detected at run-time has examples (copied from that thread) to determine language differences, for example by exploiting C++11 reference collapsing: 此线程在运行时可以检测到C ++ 03和C ++ 0x之间的差异(如果有的话)有示例(从该线程复制)以确定语言差异,例如通过利用C ++ 11引用折叠:
template <class T> bool f(T&) {return true; }
template <class T> bool f(...){return false;}
bool isCpp11()
{
int v = 1;
return f<int&>(v);
}
and c++11 allowing local types as template parameters: 和c ++ 11允许本地类型作为模板参数:
template <class T> bool cpp11(T) {return true;} //T cannot be a local type in C++03
bool cpp11(...){return false;}
bool isCpp0x()
{
struct local {} var; //variable with local type
return cpp11(var);
}
本文探讨了C++03与C++11标准下代码行为的不同,包括类型转换、异常处理、容器操作、字符串处理等方面的变化。通过具体示例展示了两版标准下相同代码可能产生的不同结果。

被折叠的 条评论
为什么被折叠?



