提供初始化列表构造函数的有效方法
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 的矢量作为资源。
- 研究后发现使用完美转发或转发
参考,
Base
class 资源可以更有效地创建,因为它避免了不必要的默认构造函数调用(请更正
我,如果我错了)。
- 除了转发技术,我还想有一个
初始化列表构造函数,这样我就可以有一个聚合
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
你可以两者兼得。您可以使用将单个对象映射到 class 中的模板版本。您还可以添加一个重载以获取 std::initializer_list
这样您就可以添加多个对象,例如
void addToClass(std::initializer_list<Base> all)
{
vec.insert(vec.end(), all.begin(), all.end());
}
这会将 all
中的所有对象添加到 vec
的末尾。
假设 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 的矢量作为资源。
- 研究后发现使用完美转发或转发
参考,
Base
class 资源可以更有效地创建,因为它避免了不必要的默认构造函数调用(请更正 我,如果我错了)。 - 除了转发技术,我还想有一个
初始化列表构造函数,这样我就可以有一个聚合
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
你可以两者兼得。您可以使用将单个对象映射到 class 中的模板版本。您还可以添加一个重载以获取 std::initializer_list
这样您就可以添加多个对象,例如
void addToClass(std::initializer_list<Base> all)
{
vec.insert(vec.end(), all.begin(), all.end());
}
这会将 all
中的所有对象添加到 vec
的末尾。