简体   繁体   English

变量在其定义中的自我分配

[英]Self-assignment of variable in its definition

The following C++ program compiles just fine (g++ 5.4 at least gives a warning when invoked with -Wall ): 以下C ++程序编译得很好(g ++ 5.4至少在使用-Wall调用时发出警告):

int main(int argc, char *argv[])
{
  int i = i; // !
  return 0;
}

Even something like 甚至像

int& p = p;

is swallowed by the compiler. 被编译器吞噬了。

Now my question is: Why is such an initialization legal? 现在我的问题是:为什么这样的初始化合法? Is there any actual use-case or is it just a consequence of the general design of the language? 是否有任何实际的用例,或者它只是语言的一般设计的结果?

Just because the compiler accepts it (syntactically valid code) does not mean that it has well defined behaviour. 正因为编译器接受它(语法上有效的代码), 并不意味着它有明确定义的行为。

The compiler is not required to diagnose all cases of Undefined Behaviour or other classes of problems. 编译器不需要诊断未定义行为或其他类问题的所有情况。 The standard gives it pretty free hands to accept and translate broken code, on the assumption that if the results were to be undefined or nonsensical the programmer would not have written that code. 该标准允许它非常自由地接受和翻译损坏的代码,假设如果结果是未定义的或无意义的,程序员就不会编写该代码。

So; 所以; the absense of warnings or errors from your compiler does not in any way prove that your program has well defined behaviour. 来自编译器的警告或错误的缺失不会以任何方式证明您的程序具有明确定义的行为。 It is your responsibility to follow the rules of the language. 遵守语言规则是您的责任。 The compiler usually tries to help you by pointing out obvious flaws, but in the end it's on you to make sure your program makes sense. 编译器通常试图通过指出明显的缺陷,帮助你,但最终它是在确保你的程序是有意义的。

And something like int i = i; int i = i; does not make sense but is syntactically correct, so the compiler may or may not warn you, but in any case is within its rights to just generate garbage (and not tell you about it) because you broke the rules and invoked Undefined Behaviour. 没有意义,但在语法上是正确的,所以编译器可能会或可能不会警告你,但在任何情况下都只是生成垃圾的权利(而不是告诉你),因为你违反了规则并调用了未定义的行为。

I guess the gist of your question is about why the second identifier is recognized as identifying the same object as the first, in int i = i; 我猜你的问题的要点是为什么第二个标识符被识别为识别与第一个相同的对象,在int i = i; or int &p = p; int &p = p;

This is defined in [basic.scope.pdecl]/1 of the C++14 standard: 这在C ++ 14标准的[basic.scope.pdecl] / 1中定义:

The point of declaration for a name is immediately after its complete declarator and before its initializer (if any), except as noted below. 声明的声明就在其完整的声明者之后和初始化者之前(如果有的话),除非如下所述。 [Example: [例:

 unsigned char x = 12; { unsigned char x = x; } 

Here the second x is initialized with its own (indeterminate) value. 这里第二个x用它自己的(不确定的)值初始化。 —end example ] - 末端的例子]

The semantics of these statements are covered by other threads: 其他线程涵盖了这些语句的语义:

Note - the quoted example differs in semantics from int i = i; 注 - 引用的示例在语义上与int i = i; because it is not UB to evaluate an uninitialized unsigned char , but is UB to evaluate an uninitialized int . 因为评估未初始化的unsigned char不是UB,而是UB来评估未初始化的int

As noted on the linked thread, g++ and clang can give warnings when they detect this. 如链接线程所述,g ++和clang在检测到这一点时可以发出警告。


Regarding rationale for the scope rule: I don't know for sure, but the scope rule existed in C so perhaps it just made its way into C++ and now it would be confusing to change it. 关于范围规则的基本原理:我不确定,但范围规则存在于C中,所以它可能只是进入C ++,现在改变它会让人感到困惑。

If we did say that the declared variable is not in scope for its initializer, then int i = i; 如果我们确实说声明的变量不在其初始化程序的范围内,那么int i = i; might make the second i find an i from an outer scope, which would also be confusing. 可能使第二i找到i外部范围,这也将是混乱的。

This is a side effect of the rule that a name is in scope immediately after it is declared. 这是规则的一个副作用,即名称在声明后立即在范围内。 There's no need to complicate this simple rule just to prevent writing code that's obvious nonsense. 没有必要使这个简单的规则复杂化,只是为了防止编写明显无意义的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM