8

为什么第一个注释行编译正确,而第二个没有?

为什么可以a将自身作为构造函数参数,但b不能?
两人不是在做同样的事情吗?

class Foo { Foo &operator =(Foo const &); /* Disable assignment */ };

int main()
{
    Foo a = a;  // OK
    Foo  b(b);  // error C2065: 'b' : undeclared identifier
}

更新

由于它似乎依赖于编译器,因此问题似乎比我想象的更严重。
所以我想问题的另一部分是,以下代码是否有效?

它在 GCC 中出现错误,但 Visual C++ 执行得很好。

int main()
{
    int i = 0;
    { int *i(&i); }
    return i;
}
4

2 回答 2

4

在您的第一个代码中,两个声明都应该编译。海合会就在那里。Visual C++ 编译器有错误。

在第二个代码中,内部声明不应该编译。GCC 也是正确的,而 VC++ 是错误的。

GCC 在这两种情况下都是正确的

从语法的角度来看,类似int a=a+100;and的代码int a(a+100);很好。它们可能会调用未定义的行为,具体取决于它们是在静态存储持续时间还是自动存储持续时间中创建的。

int a = a + 100; //well-defined. a is initialized to 100
                 //a on RHS is statically initialized to 0
                 //then a on LHS is dynamically initialized to (0+100).
void f()
{
   int b = b + 100; //undefined-behavior. b on RHS is uninitialized

   int a = a + 50; //which `a` is on the RHS? previously declared one?
                   //No. `a` on RHS refers to the newly declared one.
                   //the part `int a` declares a variable, which hides 
                   //any symbol with same name declared in outer scope, 
                   //then `=a+50` is the initializer part.
                   //since a on RHS is uninitialized, it invokes UB
}

请阅读与上述每个声明相关的评论。

请注意,具有静态存储持续时间的变量在编译时静态初始化为零,如果它们具有初始化程序,那么它们也在运行时动态初始化。但是具有自动存储持续时间的 POD 类型的变量不是静态初始化的。

有关静态初始化与动态初始化的更多详细说明,请参见:

于 2013-02-01T05:54:17.307 回答
1

正如您所注意到的,在您的第一个示例中,即使语法没问题,行为也是未定义的。因此允许编译器拒绝代码(但是必须保证未定义的行为;它在这里,但如果从未实际执行过无效初始化,则不会如此)。

你的第二个例子有一个类型错误:只要看到它的声明器,它就可见,特别是它在它自己的初始化程序中是可见的。MSVC++ 延迟了可见性:这是该编译器中一个已知的不合格问题。例如,使用 EDG 编译器(具有 Microsoft 模式):

$ ./cfe --strict x.c
"x.c", line 4: error: a value of type "int **" cannot be used to initialize an
          entity of type "int *"
      { int *i(&i); }
               ^

1 error detected in the compilation of "x.c".
$ ./cfe --microsoft x.c
"x.c", line 4: warning: variable "i" was declared but never referenced
      { int *i(&i); }
             ^
于 2013-02-01T15:01:54.627 回答