C ++代码可以在C ++ 03和C ++ 11中有效但是做不同的事情吗?

本文翻译自: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++03 Live example C ++ 03实例

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), value is left unmodified and failbit is set. 如果提取失败(例如,如果输入了预期数字的字母),则value保持failbit并设置failbit (until C++11) (直到C ++ 11)

If extraction fails, zero is written to value and failbit is set. 如果提取失败,则将零写入value并设置failbit If extraction results in the value too large or too small to fit in value , std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag 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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值