gcc初始化列表错误? [英] Initialization list bug in gcc?

查看:174
本文介绍了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 {} 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 Bs 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 B1s and B2s 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 and B2
  • use classname{} syntax in member initialization list of D instead of classname().

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆