English 中文(简体)
在 c++ 中隐藏 int 变量的名称
原标题:Hiding name of int variable in c++

出于好奇,我尝试了这个代码, 由访谈提问产生[*]

int main(int argc, char *argv[])
{
    int a = 1234;
    printf("Outer: %d
", a);
    {
        int a(a);
        printf("Inner: %d
", a);
    }
}

在Linux(g+4.6.3和clogg+3.0)上汇编时,输出:

Outer: 1234
Inner: -1217375632

但在Windows(VS2010)上,

Outer: 1234
Inner: 1234

其理由是,在第二个变量的复制构件完成之前,第一个变量仍然可以访问。 但我不确定这是标准行为还是微软(其他)奇格。

任何想法吗?

[*] 实际问题是:

您如何在不使用临时变量或全球变量的情况下在包含范围中具有相同名称变量值的变量范围内将变量调出?

{
    // Not at global scope here
    int a = 1234;
    {
        int a;
        // how do you set this a to the value of the containing scope a ?
    }
}
最佳回答

我看了一下标准,其实是灰色区域 但这里是我的两分钱...

3.1 声明和定义[基本def]

  1. 一份声明将名称引入翻译单位或重新宣布以前的声明所引入的名称。

  2. 声明是一个定义,除非.[无相关情况随

3.3.1 声明点

  1. 除下文[自选示例]所述的情况外,姓名的申报点是紧接其完整的申报人之后和启动人(如果有的话)之前(如果有的话)。

  2. 非本地名称仍然可见,直至隐藏该名称的本地名称声明点。

现在,如果我们假设这是内部声明的要点(3.3.1/1)

int a (a);
     ^

然后,外表应可见到点(3.3.1/2),即内部被定义的点。

问题是,在这种情况下,根据3.1.2,声明是一个定义。这意味着应该创建内向。在此之前,我无法从标准中理解外向是否仍然可见。 VS2010假设它是,而括号内的所有内容都指外向范围。然而, clogg++ 和 g+++ 将这条线作为自派行为处理,导致行为不明确。

我不知道哪种方法是正确的,但我发现VS2010更加一致:外在范围在内部完全建立之前仍然可见。

问题回答

您如何在不使用临时变量或全球变量的情况下在包含范围中具有相同名称变量值的变量范围内将变量调出?

除非外部范围可以被明确命名, 否则您无法做到这一点。 您可以明确命名全球范围、 命名空间范围和类范围, 但不指定函数或块语句范围 。


C++11 [基本镜3.cdel 3.3.2 p1 说 :

名称的宣布点 即在其完整声明者(第8条)之后,在其初始化者(如果有的话)之前,但下文所述情况除外。 [ 示例:

int x = 12;
{ int x = x; }

在此第二个 x 初始化为其本身的( 不确定) 值 。 - end example

MSVC 正确执行此示例, 但是当初始化器使用括号而不是指派语法时, 它无法正确执行此选项 。 有 < a href=" http:// connect. microsoft. com/ VisualStudio/ feedback/ details/ 695909/ c- parser-place- port- of- decrication- in- in- properly- for- couple- dicilization- syntaxes# details" rel= “ nofollow norefererr" > a bug 在微软连接上为此存档的 。

这里的示例程序因此错误在 VS 中行为不正确 。

#include <iostream>

int foo(char) { return 0; }
int foo(int) { return 1; } 

int main()
{
    char x =  a ;
    {
        int x = foo(static_cast<decltype(x)>(0));
        std::cout << " =  initialization has correct behavior? " << (x?"Yes":"No") << ".
";
    }
    {
        int x(foo(static_cast<decltype(x)>(0)));
        std::cout << " ()  initialization has correct behavior? " << (x?"Yes":"No") << ".
";
    }
}

C++包括以下注。

[注:涉及不确定值的操作可能造成不确定的行为。

然而,本说明指出,操作 may 会导致未定义的行为, 不一定是 do 。 上述链接的错误报告包括微软确认这是一个错误, 而不是程序触发未定义的行为 。

“强力”编辑:<强力':

您如何在不使用临时变量或全球变量的情况下在包含范围中具有相同名称变量值的变量范围内将变量调出?

如果您想要获得关于措辞的技术性, 它很容易。 “ 临时” 在 C+++( 见 §12.2) 中有特定的含义 ; 您创建的任何指定变量都不是临时的 。 因此, 您可以创建一个本地变量( 即 not 临时), 初始化的值正确 :

int a = 1234;
{ 
   int b = a;
   int a = b;
}

更为合理的一种可能性是,在外部范围中提及变量:

int a = 1234;
{ 
    int &ref_a = a;
    int a = ref_a;
}

这根本不会产生额外的变量。 它只是为外部范围的变量创建了别名。 由于别名有不同名称, 我们保留在外部范围的变量访问权限, 没有定义变量( 临时的或其他的) 。 许多引用在内部作为指针执行, 但在此情况下( 至少是一个现代的编译器和优化打开) 我期待它不会是 -- 别名实际上会被当作外部范围变量的不同名称处理( 与 VC+++ 快速测试显示它以这种方式运作 -- 生成的组装语言根本不使用 < code> ref_ a )。

另一种类似的可能方式是:

const int a = 10;
{ 
    enum { a_val = a };
    int a = a_val;
}

这与引用有些相似, 但在此情况下, 关于 < code> a_ val 是否可被称为变量, 不存在任何甚至可以争论的空间 -- 绝对是 non a变量。 问题在于, 查点只能以恒定表达式初始化, 因此, 我们必须将外部变量定义为 < code> a_ val , 这样它才能工作 。

我怀疑其中任何一种情况是访谈者真正想要的,但是他们都回答所说的问题。第一(当然)是术语定义的纯技术性。第二(当然)可能仍有一些争议(许多人认为引用是变量 ) 。 尽管它限制了范围,但对于第三(第三)没有疑问或争论的余地。

您自己初始化变量时正在做的是未定义的行为。 您的所有测试案例都是正确的, 这不是一个怪异。 执行中也可以将 < code> a 初始化为 < code> 123456789 , 它仍然是标准 。

<强度> 更新日期: 有关此答案的评论指出, 初始化变量本身并非未定义的行为, 但试图读取此变量是 。

您如何在不使用临时变量或全球变量的情况下在包含范围中具有相同名称变量值的变量范围内将变量调出?

无法 。 一旦宣布同名, 其余的外名无法进入。 您需要外部变量的复制件或别名, 这意味着您需要一个临时变量 。

我感到惊讶的是,即使警示级别被调高, VC++ 也没有在这条线上抱怨:

int a(a);

视觉 C++ 有时会警告您要隐藏变量( 可能只有衍生类成员才能隐藏 ) 。 在初始化之前告知您正在使用一个值通常也很好, 这里的情况就是这样 。

查看生成的代码, 它碰巧将内部初始化到与外体相同的值, 这是因为它留下了什么 留在一个登记册中。





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?