本文介绍了是否合法使用initializer_list来初始化派生类型的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个类带有初始化列表构造函数 std :: initializer_list< B> 。使用类 D 的对象的初始化器列表合法初始化它,其中 D 派生自 B ?

  #include< initializer_list& 

struct B {
B(int){}
};

struct D:public B {
D(int s):B(s){}
};

struct Foo {
Foo(std :: initializer_list< B> l){}
};

void main(){
Foo f {D {1},D {2}};
}

如果不合法,或者只是未定义的行为?



我在Visual Studio 2013 Update 1中尝试过这个代码。它编译,但当我运行它,我可以看到


  1. 为第一个对象创建 D 类的对象 D {1} (让调用 tempD1 )。 D 调用构造函数,然后调用 B 构造函数。

  2. tempD1 移至新的 B 物件( tmpB1 ) : B 调用构造函数。

  3. 第二个对象 D {2} ( tmpD2 , tmpB2 )。

  4. Foo 初始化列表构造函数被调用。这一切都很好。

  5. 析构函数 tmpB2 tmpD2 调用两次

  6. 析构函数 tmpD1

    我猜是编译器的一个错误(调用一个析构函数两次,缺少另一个)。但我不知道如果使用std :: initializer_list是合法的。



    (修正关于'D'或'A'名称的混淆)

    解决方案

    从 std :: initializer_list< D> 到 std :: initializer_list< B> 的转换有效...

    并且用 D 构造 std :: initializer_list< B> 有效...



    但您将拥有


    Well, maybe from the title is not clear what I'm actually asking.

    I have a class with an initializer-list constructor std::initializer_list<B>. Is legal initialize it with an initializer list of objects of class D, where D is derived from B?

    #include <initializer_list>
    
    struct B {
        B(int) {}
    };
    
    struct D: public B {
        D(int s): B(s) {}
    };
    
    struct Foo {
        Foo(std::initializer_list<B> l) {}
    };
    
    void main() {
        Foo    f{ D{ 1 }, D{ 2 } };
    }
    

    If is not legal, is that ill-formed? or just undefined behavior?

    I've tried that code in Visual Studio 2013 Update 1. It compiles, but when I run it, I can see (debugging) how:

    1. An object of class D is created for the first object D{1} (let call tempD1). D constructor is invoked and then the B constructor.
    2. The base of tempD1 is moved to a new B object (tmpB1): B move constructor is invoked.
    3. The same for the second object D{2} (tmpD2, tmpB2).
    4. Foo initializer-list constructor is invoked. All fine at this point.
    5. destructor of tmpB2 is invoked once.
    6. destructor of tmpD2 is invoked twice.
    7. destructor of tmpD1 is invoked once.

    I guess is a bug of the compiler (calling one destructor twice and missing the other one). But I'm not sure if that use of std::initializer_list is legal yet.

    (Fixed the confusions about 'D' or 'A' name)

    解决方案

    The conversion from std::initializer_list<D> to std::initializer_list<B> is valid...
    And construct std::initializer_list<B> with some D is also valid...

    But you will have object slicing

    这篇关于是否合法使用initializer_list来初始化派生类型的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 11:59