老问题,但还有更优雅的做法。

在右值引用和移动语义部分,其实我们的核心在于减少了程序运行中对变量的拷贝次数(这仅是个人直观的理解)。其实在C++11的容器中,还有一种优雅的方式可以达到这一目的。

1. 引例

考虑下面的Rect类:

struct Rect
{
    Rect(int l, int t, int r, int b)
        :left{l}, top{t}
        ,right{r}, bottom{b}
    {}
    int left;
    int top;
    int right;
    int bottom;
};

如果我们需要向容器添加Rect对象时,代码大致是这样的:

std::list<Rect> rlist;
rlist.push_front(Rect(10, 10, 20, 20));

在调用push_front时,首先构造一个临时的Rect对象传递给push_front方法,然后在push_front的内部,在复制一个Rect对象添加到容器中。全过程会发生一次创建动作和一次拷贝动作,才能将对象的内容添加到list当中去(其他容器同理)。

2. emplace方法

为了减少拷贝动作的次数,当然可以使用右值引用参数的成员函数。除此之外,C++11还提供了另一种方法:emplace成员。使用这个成员可以直接传递用于生成对象的参数,对象的创建过程交给容器去执行

std::list<Rect> rlist;
rlist.emplace_front(10, 10, 20, 20);

用法非常简单,只要保证参数和元素构造函数的参数相同即可。除了emplace_front以外,C++11还提供了emplace和emplace_bak方法,分别对应insert和push_back方法。