为什么"int i = i;"是合法的?
Why is 'int i = i;' legal?
可能的重复项:
int var = 1;void main() { int i = i; }
以下代码可以在 g++ 和 Visual C++ 下通过编译。 为什么它是合法的? 它看起来不合理,可能会导致隐藏的错误。
int main() {
int i = i;
}
编辑:它在语法上是合法的,但如果使用 x
会导致未定义的行为。
这是不合法的,因为您正在为一个未初始化的变量分配另一个(嗯,相同的)未初始化的变量。仅仅因为它编译并不意味着它是合法的。C++语法上是有效的,是的,但不合法。
分配运算符的右侧必须在分配时进行全面评估。在这种情况下,这是 i
,它没有初始化。
感谢史蒂夫·杰索普(Steve Jessop),他挖出了这句话:
4.1/1,左值到右值转换
[...]如果对象未初始化,则需要这样做的程序 转换具有未定义的行为。
语法允许它的原因是,在某些奇怪的情况下,您可能希望通过指针或引用在其自己的初始值设定项中使用变量:
struct ThingManager {
void *thing;
ThingManager(void *thing) : thing(thing) {}
void Speak() {
if (thing == (void*)this) {
std::cout << "I'm managing myselfn";
} else {
std::cout << "I'm managing " << thing << "n";
}
}
};
ThingManager self_manager(&self_manager);
ThingManager other_manager(&self_manager);
因此,C++允许您在其自己的初始值设定项表达式中引用对象(其名称在范围内)。然后,与C++中一样,确保您的实际上没有使用未初始化的值(您的示例,int i = i;
确实使用未初始化的值)是您的问题。
编译器可能有助于识别未初始化值的用法,但标准不需要这样做。
你可以让g++
用-Winit-self
(结合-Wuninitialized
)警告你这个用例,如果你把警告当作错误,它应该满足你的痒。
这种使用复制构造函数进行自我初始化的技术有时用于禁止执行全局对象的默认构造函数/初始值设定项。如果全局对象的默认构造函数只是0
初始化对象,但在执行构造函数之前使用了该对象,则可能需要这样做。作为对 C 的回归,全局变量0
在程序启动时初始化,然后C++运行时开始执行全局构造函数。对于那些将执行的已定义构造函数只是0
对象,自初始化不会造成任何伤害的狭窄情况。
在一般情况下,复制构造函数自初始化是一种不好的做法,因为它通常会导致与使用未初始化变量相同的问题(即未定义的行为)。在OP问题的特定示例中,i
是main
的本地,因此是未初始化的。读取未初始化变量的结果始终是未定义的行为。
您可以使用任何先前声明的变量作为另一个变量的初始化器。
在这种情况下,编译器一旦解析int i
就会将其添加到符号表中,因此当它看到= i
初始化器时,可以从前面的声明中解析符号。
这不是一个错误,因为编译器可以理解它,因为它可以生成代码,这些代码明确地完全按照源代码指定的方式执行,即使它在语义上是可疑的。 C 和 C++ 的哲学是编译任何可能以语法方式编译的东西。 语义错误通常只发出警告,并且只有在启用此类警告时才发出警告。
- 为什么在全局范围内使用"extern int a"似乎不行?
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 为什么我无法更改"set<set>"循环中的值<int>
- 如果"new int"返回"int*",那么为什么"new int[n]"不返回"int**"?
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 为什么将双精度转换为 int 似乎在第 16 位数字之后将其四舍五入?
- 为什么 int 类型的枚举类值不能用作 int
- 为什么 'main' 函数中的局部 int 变量会自动初始化?
- 为什么我会收到此错误?无法将 {lb, ub} 从<大括号括起来的初始值设定项列表>转换为 float(**)(float*, int)
- 为什么int myVar{5}给出错误并且不起作用?
- 为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?
- 为什么"fun(i)"被推导出为"fun<int&>"而不是"fun<int>",因为"i"是"int"的类型而不是参考?
- 为什么 c++ 中的 main() 函数不采用除 int 和 void 之外的任何其他返回类型
- 为什么我可以从C++文件中读取 int 值,但不能浮点?
- 为什么即使此代码使用 int,仍被视为 VLA?
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 查找最大的无符号 int ....为什么这不起作用?
- const int为什么更改值
- strlen to int 为什么我不能这样做?