在声明C++中,将全局变量分配给同名的局部作用域变量。

huangapple go评论51阅读模式
英文:

assigning a global variable to the same named local scope variable in declaration C++

问题

#include <iostream>
using namespace std;

int x = 1;

int main() {
	// int x = 1;	-- 相同的行为
	{
		int x = x;
		cout << x << endl;
	}
}

为什么上面的程序会打印0?我以为应该打印1。

这是否符合标准预期行为?我使用的是g++ (GCC) 12.2.0。

英文:
#include <iostream>
using namespace std;

int x = 1;

int main() {
	// int x = 1;	-- same behaviour
	{
		int x = x;
		cout << x << endl;
	}
}

Why does the above program print 0? I thought it should print 1.

Is this expected behaviour as per standard? I'm using g++ (GCC) 12.2.0

答案1

得分: 2

int x = 1;
void f() {
int x = 3;
std::cout << x << '\n';
}

在这里,局部变量 x 遮蔽了全局变量 x,输出语句将输出局部变量 x 的值,即 3。很简单。

如果你需要在函数内部使用全局变量 x,你可以使用作用域限定符来命名它:

int x = 1;
void f() {
int x = 3;
std::cout << ::x << '\n'; // 注意 x 前面的 ::
}

由于作用域限定符,::x 引用全局变量 x(这就是 :: 的含义),所以输出语句将输出全局变量 x 的值,即 1

现在是一个奇怪的情况:

int x = 1;
void f() {
int x = x;
std::cout << x << '\n';
}

同样,变量名 x 遮蔽了全局变量 x,所以 int x = x; 使用自身的值初始化了新创建的 x。这没有意义。正如问题的注释所指出的那样,结果是未定义行为。

但由于目标是使用全局变量 x 的值初始化局部变量 x,答案现在应该显而易见:

int x = 1;
void f() {
int x = ::x;
std::cout << x << '\n';
++x;
std::cout << x << '\n';
std::cout << ::x << '\n';
}

现在局部变量 x 被全局变量 x 的值初始化,第一个输出语句输出局部变量 x 的值,即 1。为了完整起见,在修改局部变量 x 的值后,第二个输出语句输出局部变量 x 的新值,即 2。第三个输出语句输出全局变量 x 的值,仍然是 1

如果你真的想让自己困惑,你可以在嵌套作用域中遮蔽一个变量名,就像这样:

void f() {
int x = 1;
{
int x = 2;
// ??
}
}

在这里,在标记为 // ?? 的地方,没有语法可以访问外部作用域中的 x

英文:

Let's simplify for a moment:

int x = 1;
void f() {
    int x = 3;
    std::cout &lt;&lt; x &lt;&lt; &#39;\n&#39;;
}

Here, the local x hides the global x, and the output statement writes out the value of the local x, namely, 3. Simple enough.

If you need to use the global x inside that function you can name it with a scope qualifier:

int x = 1;
void f() {
    int x = 3;
    std::cout &lt;&lt; ::x &lt;&lt; &#39;\n&#39;; // note the :: in front of x
}

Because of the scope qualifiers, ::x refers to the global x (that's what :: means), so the output statement writes out the value of the global x, namely, 1.

Now the weird case:

int x = 1;
void f() {
    int x = x;
    std::cout &lt;&lt; x &lt;&lt; &#39;\n&#39;;
}

Again, the name x hides the global x, so int x = x; initializes the newly-created x with its own value. Which doesn't make sense. And as the comments to the question so helpfully pointed out, the result is undefined behavior.

But since the goal is to initialize the local x with the value of the global x, the answer should now be obvious:

int x = 1;
void f() {
    int x = ::x;
    std::cout &lt;&lt; x &lt;&lt; &#39;\n&#39;;
    ++x;
    std::cout &lt;&lt; x &lt;&lt; &#39;\n&#39;;
    std::cout &lt;&lt; ::x &lt;&lt; &#39;\n&#39;;
}

Now the local x gets initialized with the value of the global x, and the first output statement writes out the value of the local x, namely 1. Just for completeness, after the modification of the value of the local x, the second output statement writes out the new value of the local x, namely 2. The third output statement writes out the value of the global x, which is still 1.

If you're really into confusing yourself, you can hide a name with a nested scope, like this:

void f() {
    int x = 1;
    {
    int x = 2;
    // ??
    }
}

Here, at the line marked // ??, there's no syntax for getting at the x in the outer scope.

huangapple
  • 本文由 发表于 2023年4月1日 00:53:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75900945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定