具有嵌套对象优化的 C++ emplace_back

c++ emplace_back with nested objects optimization

本文关键字:C++ emplace back 优化 嵌套 对象      更新时间:2023-10-16

我对emplace_back的行为有点困惑。 一起来看看吧。

struct innerObject
{
innerObject(int );
};
class outterObject
{
innerObject member;
public:
outterObject(innerObject member);
};
int main()
{
std::vector<outterObject> v1;
v1.emplace_back(5);
}

所以在这种情况下,我们可以传递整数并且它有效。

如果innerObject需要两个int而不是一个来构造,那么构造函数呢?v1.emplace_back(5,5)v1.emplace_back({5,5})或我尝试的任何其他组合都不起作用。有没有可能?有没有更好的选择来制作这样的东西?(优化)

避免任何类型的复制/移动的唯一方法是让外部类型通过提供通用构造函数来选择加入此类操作:

template <typename A0, typename... Args,
std::enable_if_t<
!std::is_same_v<std::decay_t<A0>, outterObject> &&
std::is_constructible_v<outterObject, A0, Args...>
, int> = 0>
outterObject(A0&& a0, Args&&... args)
: member(std::forward<A0>(a0), std::forward<Args>(args)...)
{ }

这将允许您编写v1.emplace_back(10, 20)如果innerObject可以从 2int秒构造。

如果这看起来有点矫枉过正,你总是可以做v1.push_back({{10, 20}})。请注意,与emplace_back()不同,push_back()不会推断其参数类型 - 它只是T const&T&&。这允许您使用{}s。

它适用于一个参数的原因是 innerObject 类的单个 int 构造函数充当转换构造函数。换句话说,outterObject 构造函数采用 innerObject 对象,并且由于转换构造函数规则,它将单个 int 参数转换为 innerObject。

未使用说明符显式声明的构造函数和 可以用单个参数调用(直到 C++11)称为 转换构造函数。 链接

转换构造函数仅适用于单参数构造函数。

如果你在 innerObject 构造函数采用单个 int 之前编写显式,你会看到它不会编译,因为 "explicit" 关键字不允许 int 参数自动创建一个 innerObject 传递给 outerObject 构造函数:

v1.emplace_back(5); // v1 is a vector of outerObject.

这工作的唯一原因是 5 参数通过其采用 int 的非显式构造函数转换为 innerObject。此转换构造函数行为仅适用于单参数构造函数。

如果需要,可以将两个参数构造函数添加到innerObject:

innerObject(int x, int y)
{
std::cout << "constructor innerObject" << std::endl;
}

然后:

v1.emplace_back(innerObject(5, 6));

您可以简单地构造内部对象,而不是emplace_back:

v1.emplace_back(innerObject{10, 20});

或者,您可以为outerObject添加一个构造函数,该构造函数接受两个参数和 than 调用innerObject构造函数。在这种情况下,您可以这样称呼它:

v1.emplace_back(10, 20);