合法使用initializer_list来初始化派生类型的对象吗?

时间:2014-02-12 15:05:06

标签: c++ inheritance c++11 initializer-list object-slicing

好吧,也许从标题中不清楚我实际上在问什么。

我有一个带有初始化列表构造函数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}tmpD2tmpB2)也是如此。
  4. Foo初始化列表构造函数被调用。此时一切都很好。
  5. tmpB2的析构函数被调用一次。
  6. tmpD2的析构函数被调用两次
  7. tmpD1的析构函数被调用一次。
  8. 我猜是编译器的一个错误(调用一个析构函数两次而错过另一个析构函数)。但我不确定是否使用std :: initializer_list是合法的。

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

1 个答案:

答案 0 :(得分:4)

std::initializer_list<D>std::initializer_list<B>的转换无效... 但构建std::initializer_list<B>并使D有效{(这就是这里发生的事情)......

但你会object slicing