C++ 11为语言的核心方面带来了新的关键词和新的变化.
那么可以在C++ 11和pre-C++ 11中成功编译同一段代码,但是从每个二进制文件中得到不同的结果吗?通过 pre-C++ 11,我指的是C++ 98,C++ 03或C++ TR1.
我问的原因是因为我有一堆小程序都是用C++编写的.我不知道每个编写的程序都考虑了什么标准.如果它们都在C++ 11和早期标准中编译,那么这些程序的行为是否保证是相同的?我想在C++ 11中编译它们(如果它们可以),但是如果考虑到早期标准,可以避免任何可能导致程序行为不同的细微变化.
非常感谢工作范例.
第7.2节枚举声明没有说明有关范围枚举的内容operator!=()
和内容operator==()
.但是下面的代码编译.
#include <iostream>
enum class Month{jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov , dec};
int main()
{
Month a = Month::feb;
Month b = Month::jul;
Month c = a;
if( a != b ) std::cout << "a |= b" << '\n';
if( a == c ) std::cout << "a == c" << '\n';
}
Run Code Online (Sandbox Code Playgroud) 现在,我并不是说我认为这可以接近正确的编码实践(假设它甚至可能); 这个问题源于凌晨2点的错误:假设类定义类似于以下内容:
class myClass
{
public:
void myMethod(const int & name);
}
Run Code Online (Sandbox Code Playgroud)
和定义:
void myClass::myMethod(const int & altName)
{
//manipulate altName
}
Run Code Online (Sandbox Code Playgroud)
请注意,声明和定义的参数都是const int&类型,唯一的区别是变量名称.我知道这不会(在Visual Studio 2012中)抛出编译器错误或警告,但是在运行程序时是否会导致错误?
谢谢!
我的一些同事今天进行了辩论,我想澄清一下.它是关于表达式中的评估顺序和序列点.标准中明确指出,C/C++在表达式中没有从左到右的评估,这与Java之类的语言不同,后者保证具有从左到右的顺序.因此,在下面的表达式中,在评估最右边的操作数(C)之前,对二进制操作中最左边的操作数(B)的求值进行排序:
A = B B_OP C
Run Code Online (Sandbox Code Playgroud)
根据序列前序列(Undefined Behavior)和Bjarne的TCPPL 3rd ed 下的CPPReference,下面的表达式是UB
x = x++ + 1;
Run Code Online (Sandbox Code Playgroud)
它可以被解释为像BUT这样的编译器,据说下面的表达式在C++ 11中显然是一个明确定义的行为
x = ++x + 1;
Run Code Online (Sandbox Code Playgroud)
那么,如果上面的表达式定义得很清楚,那么"命运"是什么呢?
array[x] = ++x;
Run Code Online (Sandbox Code Playgroud)
似乎没有定义后增量和后减量的评估,但定义了预增量和预减量.
注意:这不用于实际代码中.Clang 3.4和GCC 4.8明确警告了增量前后序列点.
假设函数参数将在堆栈上顺序传递是否安全?
例如,无论编译器设置如何,都foo
保证输出x y z
?
void foo(int x, int y, int z) {
int *vector = &x;
for(int i = 0; i < 3; i++) {
std::cout << vector[i] << " ";
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用visual studio并且它确实有效,但我不确定这种行为是否得到保证.
在C++标准中,它是否说在命名空间范围之外定义命名空间的变量成员的方法是通过extern
在变量成员的声明中使用说明符?
§3.4.1/ 14提到这个"en passant":
如果命名空间的变量成员在其命名空间的范围之外定义,则会查找成员定义中出现的任何名称(在declarator-id之后),就好像成员的定义出现在其名称空间中一样.[例如:
namespace N {
int i = 4;
extern int j;
}
int i = 2;
int N::j = i; // N::j == 4
Run Code Online (Sandbox Code Playgroud) 第§8.3.5/ 8段(强调我的):
如果参数的类型包括"指向T的未知边界的数组的指针"或"对T的未知边界的数组的引用"形式的类型,则该程序是不正确的.函数不应具有类型数组或函数的返回类型,尽管它们可能具有类型指针的返回类型或对此类事物的引用.虽然可以有函数指针数组,但是不应该有函数数组.
§8.5.3/ 5的要点(5.2.1)和(5.2.1.1)(重点是我的):
(5.2.1) - 如果是初始化表达式
(5.2.1.1) - 是xvalue(但不是位字段),类prvalue, 数组prvalue或函数lvalue,"cv1 T1"与"cv2 T2"引用兼容,或者
如果我对我的假设(在标题中)错了,我会很感激有一个产生prvalue数组的例子.
在关于C和C++中的空指针的这个问题的讨论之后,我想在这里分开结束问题.
如果可以从C和C++标准推断(答案可以针对两个标准),取消引用其值等于nullptr
(或(void *)0
)值的指针变量是未定义的行为,是否意味着这些语言需要地址中的特殊值空间已经死了,这意味着它除了代表的作用外无法使用nullptr
?如果系统在相同的地址处具有真正有用的功能或数据结构,该nullptr
怎么办?这应该永远不会发生,因为编译器编写的每个系统都需要找出一个非冲突的空指针值,这是编译器的编写者责任吗?或者,在"未定义的行为模式"下编程以实现其意图时,需要访问此类函数或数据结构的程序员是否满足?
这看起来模糊了编译器和计算机系统角色的界限.我会问这样做是否正确,但我想这里没有空间.
在MVSC中,当我#include <stdint.h>
,我最终得到UINTX_C和INTX_C宏的以下定义:
#define INT8_C(x) (x)
#define INT16_C(x) (x)
#define INT32_C(x) ((x) + (INT32_MAX - INT32_MAX))
#define UINT8_C(x) (x)
#define UINT16_C(x) (x)
#define UINT32_C(x) ((x) + (UINT32_MAX - UINT32_MAX))
Run Code Online (Sandbox Code Playgroud)
很明显,8位和16位宏只是通过未经修改的常量,这并不能完全执行它们的设计.是否有一个不同的文件包含在Windows上以获得正确的定义?
§3.5[basic.link]/3(我的重点):
具有命名空间作用域(3.3.6)的名称具有内部链接(如果它的名称)
(3.1) - 显式声明为static的变量,函数或函数模板; 要么,
(3.2) - 一个非易失性变量,显式声明为const或constexpr,既未显式声明为extern,也未声明为具有外部链接 ; 要么
(3.3) - 匿名工会的数据成员.
我认为(3.2)中粗体字符中的短语是多余的,除非有人能给出一个显式声明const
但未声明的变量的例子extern
,以及之前声明external linkage
的变量,以及结果变量具有的变量external linkage
.
c++ ×10
language-lawyer ×10
c++11 ×5
c ×1
c++14 ×1
class ×1
declaration ×1
definition ×1
enums ×1
linkage ×1
macros ×1