[英]c++ emplace_back with nested objects optimization
I was slightly confused about behavior of emplace_back. 我对emplace_back的行为感到有些困惑。 Let's have a look.
我们来看一下。
struct innerObject
{
innerObject(int );
};
class outterObject
{
innerObject member;
public:
outterObject(innerObject member);
};
int main()
{
std::vector<outterObject> v1;
v1.emplace_back(5);
}
So in this case we could pass integer and it works. 因此,在这种情况下,我们可以传递整数并且它可以工作。
What about constructor if innerObject
needed two int
s to construct from instead of just one? 如果
innerObject
需要两个 int
来构造而不是一个,那么构造函数呢? Neither v1.emplace_back(5,5)
nor v1.emplace_back({5,5})
nor any other combination which I tried works. v1.emplace_back(5,5)
或v1.emplace_back({5,5})
或我尝试过的任何其他组合都v1.emplace_back(5,5)
。 Is it somehow possible? 有可能吗? Is there any better option to make such things?
有没有更好的选择来制作这样的东西? (optimized)
(优化)
The only way to avoid any kind of copy/move is for the outer type to opt-in to that sort of operation by providing a generalized constructor: 避免任何类型的复制/移动的唯一方法是,通过提供通用的构造函数,使外部类型选择加入此类操作:
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)...)
{ }
This would let you write v1.emplace_back(10, 20)
if innerObject
were constructible from 2 int
s. 如果
innerObject
是可从2个int
构造的,则可以编写v1.emplace_back(10, 20)
。
If that seems like too much overkill, you can always just do v1.push_back({{10, 20}})
. 如果这看起来过于
v1.push_back({{10, 20}})
过正,则始终可以执行v1.push_back({{10, 20}})
。 Note that push_back()
, unlike emplace_back()
, doesn't deduce its argument type - it's just T const&
or T&&
. 请注意,与
emplace_back()
不同, push_back()
不会推断出其参数类型-只是T const&
或T&&
。 This allows you to use {}
s. 这使您可以使用
{}
。
The reason it works for one argument is that the single int constructor for your innerObject class acts as a converting constructor. 它对一个参数起作用的原因是您的innerObject类的单个int构造函数充当转换构造函数。 In other words outterObject constructor takes an innerObject object, and due to the converting constructor rules, it converts the single int argument to an innerObject.
换句话说,outterObject构造函数接受一个innerObject对象,由于转换构造函数规则,它将单个int参数转换为一个innerObject。
A constructor that is not declared with the specifier explicit and which can be called with a single parameter (until C++11) is called a converting constructor.
未使用说明符进行显式声明的构造函数,可以使用单个参数 (直到C ++ 11)调用该构造函数,该构造函数称为转换构造函数。 Link
链接
Converting constructors only work for single argument constructors. 转换构造函数仅适用于单参数构造函数。
If you write explicit before the innerObject constructor taking a single int, you'll see it won't compile, because "explicit" keyword disallows the int argument to automatically create an innerObject to pass to the outerObject constructor: 如果在innerObject构造函数采用单个int之前编写显式代码,则会看到它不会编译,因为“ explicit”关键字不允许int参数自动创建要传递给externalObject构造函数的innerObject:
v1.emplace_back(5); // v1 is a vector of outerObject.
The only reason this works is that the 5 argument is converted into an innerObject via its non-explicit constructor taking an int. 起作用的唯一原因是5参数通过其非显式构造函数采用int形式转换为innerObject。 This converting constructor behaviour only works for single argument constructors.
这种转换构造函数的行为仅适用于单参数构造函数。
If you want you can add the two argument constructor to innerObject: 如果需要,可以将两个参数构造函数添加到innerObject中:
innerObject(int x, int y)
{
std::cout << "constructor innerObject" << std::endl;
}
And then: 接着:
v1.emplace_back(innerObject(5, 6));
You can simply construct inner object and than emplace_back: 您可以简单地构造内部对象,而不是emplace_back:
v1.emplace_back(innerObject{10, 20});
Alternatively, you can add a constructor for outerObject
which accepts two arguments and than calls innerObject
constructor. 另外,您可以为
outerObject
添加一个构造函数,该构造函数接受两个参数,然后调用innerObject
构造函数。 In this case you would call it this way: 在这种情况下,您可以这样称呼:
v1.emplace_back(10, 20);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.