简体   繁体   English

C ++ emplace_back与嵌套对象优化

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM