gcc初始化列表错误? [英] Initialization list bug in gcc?
问题描述
考虑以下代码,其中 B
是由 D
至 B1
和 B2
:
#包括< iostream>
class B
{
保护:
int x;
保护:
B(int x):x {x} {std :: cout<< x<< std :: endl;}
};
class B1:虚拟公共B
{
保护:
B1():B(0){}
};
class B2:虚拟公共B
{
保护:
B2():B(10){}
};
class D:public B1,public B2
{
public:
D():B(99),B1(),B2( ){}
void print(){std :: cout<< 最后:<< x<< std :: endl;}
};
int main(){
D d;
d.print();
返回0;
}
查看工作示例这里。我在 B
的构造函数中使用输出,并在 D
之后使用了输出,以便跟踪发生了什么。当我用g ++ - 4.8.1编译上面的例子时,一切正常。它打印
99
最终:99
因为 B
的构造函数被大多数派生类调用过一次( D
x 的最终值。
现在出现了一个奇怪的部分:如果我(),B1(),B2(){}
/ code>
添加到新的统一初始化语法中,即
D():B {99},B1 {},B2 {} {}
奇怪的事情发生。其一,它不会再编译,错误
prog.cpp:在构造函数'D :: D() ':
prog.cpp:17:5:error:'B1 :: B1()'受保护
B1():B(0){}
^
prog .cpp:31:27:error:在此上下文中
D():B {99},B1 {},B2 {} {}
(和 B2
相同,参见这里)这是没有意义的,因为我在派生类中使用它,所以 protected
应该没问题。如果我纠正这一点,并使构造函数 B1
和 B2
public而不是protected,所有东西都会被搞砸了请参阅 here ),因为输出成为
99
0
10
最终:10
因此,事实上, B1
s和 B2
的构造函数初始化<$ c仍然执行$ c> B ,甚至改变 x
的值。虚拟继承不应该是这种情况。请记住,只有我改变了的东西是
- public而不是
B1
和B2
- 使用
classname {} $ c $在$
D
的成员初始化列表中,而不是classname()
。
我无法相信gcc中这样一个基本的东西出错了。但是我在本地机器上用clang进行了测试,所有三种情况都按照预期进行编译和运行(即像上面的第一个例子)。编辑:我的第一个搜索莫名其妙地没有提出来,但现在我发现了
a href =https://stackoverflow.com/questions/12313292/why-does-this-snippet-using-uniform-initialization-compile-with-g4-6-but-not-g?rq=1> this其他问题,至少显示受保护/公开错误。但是,这是gcc-4.7,所以我预料它会在gcc-4.8中处理。所以,我应该总结初始化列表只是从根本上搞乱了gcc!?我不知道是否太迟回答这个问题,但是你的代码在GCC 4.9.2中编译得很好!
〜$ g ++ -std = c ++ 11 test .cpp
〜$。/ a.out
99
最终:99
〜$ gcc --version
gcc(GCC)4.9.2
Copyright(C)2014 Free Software Foundation,Inc.
这是免费软件;请参阅复制条件的来源。没有任何b $ b保修;甚至不适用于适销性或针对特定用途的适用性。
Consider the following code, where B
is a virtual base class inherited by D
through B1
and B2
:
#include <iostream>
class B
{
protected:
int x;
protected:
B(int x) : x{x}{std::cout << x << std::endl;}
};
class B1 : virtual public B
{
protected:
B1() : B(0){}
};
class B2 : virtual public B
{
protected:
B2() : B(10){}
};
class D : public B1, public B2
{
public:
D() : B(99), B1(), B2() {}
void print() {std::cout << "Final: " << x << std::endl;}
};
int main() {
D d;
d.print();
return 0;
}
See working example here. I use outputs in B
's constructor and after D
has been completely constructed to keep track of what's going on. Everything works fine, when I compile the above example with g++-4.8.1. It prints
99
Final: 99
because B
s constructor is called once from the most derived class (D
) and that also determines the final value of x
.
Now comes the strange part: If I change the line
D() : B(99), B1(), B2() {}
to the new uniform initialization syntax, i.e.
D() : B{99}, B1{}, B2{} {}
strange things happen. For one, it doesn't compile anymore, with the error
prog.cpp: In constructor ‘D::D()’:
prog.cpp:17:5: error: ‘B1::B1()’ is protected
B1() : B(0){}
^
prog.cpp:31:27: error: within this context
D() : B{99}, B1{}, B2{} {}
(and the same for B2
, see here) which doesn't make sense because I am using it in a derived class, so protected
should be fine. If I correct for that and make the constructors of B1
and B2
public instead of protected, everything gets totally messed up (see here), as the output becomes
99
0
10
Final: 10
So, in fact, the parts of B1
s and B2
s constructors that initialize B
are still executed and even change the value of x
. This should not be the case for virtual inheritance. And remember, the only things I have changed are
- public instead of protected constructors in
B1
andB2
- use
classname{}
syntax in member initialization list ofD
instead ofclassname()
.
I cannot believe such a basic thing goes wrong in gcc. But I tested it with clang on my local machine and there, all three cases compile and run as intended (i.e. like the first example above). If it's not a bug, can someone please point me to what I am missing?
EDIT: My first search somehow didn't bring it up, but now I found this other question, showing at least the protected/public error. However, this was gcc-4.7, so I would have expected it to be dealt with in gcc-4.8. So, should I conclude initializer lists are just fundamentally messed up in gcc!?
I don't know if it's too late to answer this, but your code compiles fine in GCC 4.9.2!
~$g++ -std=c++11 test.cpp
~$./a.out
99
Final: 99
~$gcc --version
gcc (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
这篇关于gcc初始化列表错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!