提供初始值设定项列表构造函数的有效方法

Efficient way of providing an initializer list constructor

本文关键字:构造函数 列表 有效 方法      更新时间:2023-10-16

假设,一个具有以下资源的类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类的向量作为资源。

  • 经过研究,我发现使用完美的转发或转发 参考,Base类资源可以更有效地创建,因为它避免了对默认构造函数的不必要调用(请更正 我,如果我错了(。
  • 除了转发技术,我还想有一个 初始值设定项列表构造函数,以便我可以有一个聚合 可启动SubClass

然后我为我的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你可以两者兼而有之。 您可以使用将单个对象扩展到类中的模板版本。 您还可以添加重载来获取std::initializer_list以便您可以添加多个对象,例如

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

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