Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 了解C+中的复制初始化+;,与显式初始化相比_C++_Constructor_Initialization - Fatal编程技术网

C++ 了解C+中的复制初始化+;,与显式初始化相比

C++ 了解C+中的复制初始化+;,与显式初始化相比,c++,constructor,initialization,C++,Constructor,Initialization,为什么第一个注释行编译正确,而第二个注释行编译不正确 为什么a本身可以作为构造函数参数,而b不能? 这两个人不是在做同一件事吗 class Foo { Foo &operator =(Foo const &); /* Disable assignment */ }; int main() { Foo a = a; // OK Foo b(b); // error C2065: 'b' : undeclared identifier } 更新 因为它似乎

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

为什么
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;
}

在第一个代码中,两个声明都应该编译。GCC就在那里。Visual C++编译器有bug。 在第二段代码中,内部声明应该而不是编译。GCC也是正确的,而VC++是错误的

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

类似于
inta=A+100的代码
inta(a+100)很好。它们可能会调用未定义的行为,这取决于它们是在静态存储持续时间还是在自动存储持续时间中创建的

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

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

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


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

您的第二个示例有一个类型错误:一个声明在其声明符被看到时就可见,尤其是在它自己的初始值设定项中。MSVC++延迟了可见性:这是该编译器中已知的不一致性问题。例如,使用EDG编译器(具有Microsoft模式):


这两种方法都是错误的,在GCC 4.7.2和CLAN 3.2上。@克里斯:哦,奇怪,我用Visual C++。那样的话,哪一个是对的?!我不确定,但我几乎每天都会在GCC和MSVC上下赌注。至少它缩小了问题的范围。实际上两者都应该编译。类似于
inta=A+100的代码
inta(a+100)很好。它们可能会调用UB,这取决于它们是在静态存储持续时间还是在自动存储持续时间中创建的?我永远不会把它描述为“严重的”,因为它只影响真正愚蠢的代码。如果
a
以前被定义为其他的东西,比如说
?还可以吗?@Mehrdad:这是重新声明,不是吗?也许在不同的范围内,是的。但是我的问题是,右边的
a
是指旧的
a
还是指新的
a
?@Mehrdad:它指的是新的
a
:部分
inta
声明了一个变量,它隐藏了在外部范围内声明的任何同名符号,然后,
=a+100
是初始值设定项部分。嗯+1很有趣,谢谢你的回答。另一方面,这个“你想把这个讨论转移到聊天吗?”的问题出现得太早了……再次感谢你的洞察力:-)。现在我知道这是一个已知的错误:-)
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
}
$ ./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); }
             ^