提供初始化列表构造函数的有效方法

Efficient way of providing an initializer list constructor

假设 class Base 具有以下资源:

struct Base
{
    int m_int;
    bool m_flag;
    float m_float;
    Base() = delete; // just to see that it didn't call
    Base(int a, bool b, float c): m_int(a), m_flag(b), m_float(c) {}

};

然后我有一个 SubClass,它有一个 Base class 的矢量作为资源。

然后我为 SubClass.

想出了以下代码
struct SubClass
{
private:
    std::vector<Base> vec;
public:
    SubClass() = delete; // just to see that it didn't call

    // Idea - 1
    //SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}

    // Idea - 2
    SubClass(std::initializer_list<Base> all): vec(all) {}

    // Idea - 3 : but no more list initialization possible
    template<typename ...Arg>
    void addToClass(Arg&& ...args)
    {
        vec.emplace_back(std::forward<Arg>(args)...);
    }
};

然后在main()中,我可以有以下两种可能性来更新SubClass中的资源:

int main()
{
    // possibility - 1
    SubClass obj
    {
       {1, true, 2.0f },
       {5, false, 7.0f},
       {7, false, 9.0f},
       {8, true, 0.0f},
    };
    //possibility - 2: without list initialization
    /*obj.addToClass(1, true, 2.0f);
    obj.addToClass(5, false, 7.0f);
    obj.addToClass(7, false, 9.0f);
    obj.addToClass(8, true, 0.0f);*/

    return 0;
}

问题 - 1:

在上述情况下,以下哪一项是有效的或好用的(良好做法)?为什么?

// Idea - 1
SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}

// Idea - 2
SubClass(std::initializer_list<Base> all): vec(all) {}

问题 - 2:

addToClass(Arg&& ...args) 功能是否与上述两个想法相似?

要事第一。

SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}

SubClass(std::initializer_list<Base> all): vec(all) {}

不要做同样的事情。第一个还需要

SubClass(std::initializer_list<Base>& all): vec(all) {}

所以你可以用左值 std::initializer_list 初始化它(可能永远不会发生,但它可能)。按值传递涵盖了这两个重载,因此它更容易编写,而且性能也差不多(需要大量操作才能真正发挥作用)

您不能将对象移出 std::initializer_list,因为对象标记为 const,所以

SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}

实际上并没有移动任何东西。

至于 addToClass 你可以两者兼得。您可以使用将单个对象映射到 class 中的模板版本。您还可以添加一个重载以获取 std::initializer_list 这样您就可以添加多个对象,例如

void addToClass(std::initializer_list<Base> all)
{
    vec.insert(vec.end(), all.begin(), all.end());
}

这会将 all 中的所有对象添加到 vec 的末尾。