C++ 表观等效表达式(类别)A和A之间的差异;,和(类别)A{};
我想知道,两者之间可能有什么内在的区别C++ 表观等效表达式(类别)A和A之间的差异;,和(类别)A{};,c++,class,extern,behavior,C++,Class,Extern,Behavior,我想知道,两者之间可能有什么内在的区别 A和A{}(A类,无构造函数) 我只是在玩代码,发现了一些非常有趣的东西,其中声明一个全局类实例为a产生了不同的结果取而代之 这很有趣,因为我明白: 在没有初始化的情况下声明类实例将调用默认构造函数(如果存在,则不带参数的构造函数) a{}是一个表达式,用于创建类实例并调用默认构造函数 所以,基本上是一样的,但是他们在一定条件下产生了不同的结果,尽管通过破坏ODR在可能的UB领域发现了它 我的问题是,如果a严格等价于A{} 从逻辑上讲,它们的内部实现之
A代码>和A{}代码>(A类,无构造函数)
我只是在玩代码,发现了一些非常有趣的东西,其中声明一个全局类实例为a与使用a{}相比,code>产生了不同的结果代码>取而代之
这很有趣,因为我明白:
- 在没有初始化的情况下声明类实例将调用默认构造函数(如果存在,则不带参数的构造函数)
a{}
是一个表达式,用于创建类实例并调用默认构造函数
所以,基本上是一样的,但是他们在一定条件下产生了不同的结果,尽管通过破坏ODR在可能的UB领域发现了它
我的问题是,如果a
严格等价于A{}代码>
从逻辑上讲,它们的内部实现之间应该存在一些差异,以产生不同的结果,而其他一切都保持完全相同。我想知道这有什么区别
我正在使用Visual studio 2017
//extern_src.cpp
class A {
public:
int a=24;
};
A extern_a; // << here, if i put {} at the end, different results comes out;
//src.cpp
#include <iostream>
class A {
public:
int a=3;
};
int main() {
extern A extern_a;
A a;
std::cout << a.a << " " << extern_a.a << std::endl;
return 0;
}
//extern\u src.cpp
甲级{
公众:
INTA=24;
};
外部人员 您已经证明您的程序违反了一个定义规则。Per:
给定这样的条件,类类型[…]可以有多个定义
在多个翻译单元中定义的名为D
的实体,然后
- 每个
D
的定义应包含相同的令牌序列和
- [……]
[…]如果D
的定义不满足这些要求,
那么行为是未定义的。
您对A
的定义不包含相同的令牌序列,因此行为未定义。当行为未定义时,所有下注都将取消。即使是同一个程序在再次编译时也可能表现出不同的行为。不是说A代码>和A{}代码>是不同的语句(或者更准确地说,是简单的声明,但不是表达式)。Per:
未定义的行为
本文件不要求的行为
[ 注意:当本文档省略时,可能会出现未定义的行为
行为的任何明确定义,或当程序使用
错误的构造或错误的数据。允许的未定义行为
范围从完全忽略情况到不可预测
结果,在翻译或程序执行过程中在
记录环境特征的方式(有无)
发出诊断消息),以终止翻译或
执行(发出诊断信息)。许多错误
程序构造不会产生未定义的行为;它们是
需要诊断。常数表达式的求值
展示在[intro]至中明确指定为未定义的行为
本文件的[cpp]([expr.const])- 尾注 ]
另请参阅以了解未定义行为的可能后果。特别是GCC的一个版本(1.17)当遇到某些未定义的行为时,试图启动游戏NetHack、Rogue和Towers of Hanoi。如果您理解您违反了合同,那么您已经知道对您的问题的回答是没有意义的。另一方面,如果您建议我们忽略ODR违反,并且它不是cru作为您观察的一部分,您为什么继续将其包含在您的回答中?为了让前面的回答更清楚-您的代码显示未定义的行为。您定义了两次类A。任何情况都可能发生。删除一个定义,它就会起作用。@那么您的问题基于两个错误的前提:(1)在违反合同并创建UB后,您可以期待任何有意义的、有用的或可预测的行为,您已经表明您知道您正在做什么,以及(2)a{}
和a
是完全相同的表达式(或者,事实上,是完全相同的表达式)不同之处在于A
的两个定义不同。它们初始化成员A
的方式不同。每个看到类A
定义的编译单元都必须看到相同的定义。作为类定义的一部分,在不同的编译单元中对成员进行不同的初始化会违反ODR和ODR意味着你的代码有未定义的行为。你对这两种语言将被翻译成同一种低级语言的期望不能保证是正确的。如果你只是想知道这两种声明之间的区别,那么就去问这个问题。不要试图用UB来框定问题,因为这样做只会使它无效“并不是说A;和A{};是不同的语句。”那么有什么区别呢?这是我这里的一个大问题。@AA;
是默认初始化,A{};
是值初始化。请参阅。