使用move插入STL容器

时间:2014-12-30 15:44:23

标签: c++11 stl

我试图更好地理解移动在用于将元素插入STL容器时的工作方式。我正在查看一个代码,其中使用new(在堆上创建)分配了一个对象。稍后,当插入完成时,似乎STL容器分配一个新对象并调用移动构造函数。有没有办法让STL容器直接使用该对象(接管已分配的对象(ptr))。

我有一些其他问题的示例代码:

#include <iostream>
#include <vector>
using namespace std;

class foo
{
    public:
        string   s1;

        foo() = default;

        foo(const foo& fm)
        { cout << "copy ctor" << endl; }

        foo(const foo&& fm)
        { cout << "move ctor" << endl; }

        foo& operator= (const foo& fm)
        { cout << "copy assign" << endl; return *this; }
};

vector<foo> vec_f;

int main()
{
    foo f1;
    vec_f.push_back(f1);
    cout << endl;

    foo f2;
    vec_f.push_back(move(f2));
    cout << endl;

    foo *f3 = new (foo);
    vec_f.push_back(*f3);
    cout << endl;

    foo *f4 = new (foo);
    vec_f.push_back(move(*f4));
    cout << endl;
}

输出如下:

copy ctor

move ctor
copy ctor

copy ctor
copy ctor
copy ctor

move ctor

f1:foo是使用copy ctor创建的。但是,这个对象是由于STL代码执行新的OR部分而创建的,这个OR部分是通过值将对象传递给函数(与STL无关,而是编译器事物)?我在猜测后者。如果是这样,当元素插入容器时,对象创建在哪里?

f2:foo是使用移动ctor,通过STL代码创建的,对吗?为什么/如何立即调用复制ctor?是因为f2是在堆栈上创建的(不是堆)?如果是这样,STL代码如何计算出来?

f3:最让我困惑的是。猜测第一个副本ctor是作为通过值传递参数的一部分而调用的(与STL无关)。如何/为什么其他两个副本被称为。

f4:STL调用move ctor,所以移动ctor可以使用foo对象的内容。是否可以使STL代码只使用ptr(因为它是在堆上创建的)。我的理解是STL容器中的对象无论如何都是在堆上创建的。

很抱歉这篇长篇文章。希望有人能说清楚。

此致 艾哈迈德。

2 个答案:

答案 0 :(得分:0)

首先要意识到的是std::move实际上并没有移动一个对象。它会在哪里移动?它只允许从移动

要意识到的第二件事是vector管理自己的记忆。您可以将许多对象移动到vector,但是您无法将vector内存放在其旁边(在这种情况下,您根本不会移动对象)

接下来是vector::push_back。这可以采用T const&T&&,具体取决于参数。只有后一种情况才有适当的形式直接将值移动到vector。第一个和第三个案例失败,因为无法移动使用的表达式。第二种情况看起来没有进行优化(副本可能会在发布版本中进行优化)。

答案 1 :(得分:0)

由于vector尺寸更改的重新分配,vector本身会进行额外的复制和移动。

您可以打印内存地址,例如cout << &vec_f[0] << endl;,并在每push_back()

之后更改其值

示例输出:

copy ctor
0077C350
move ctor
move ctor
0077C588
move ctor
move ctor
copy ctor
0077C690
move ctor
move ctor
move ctor
move ctor
0077C8A8

如果您在vec_f.reserve(4);之后添加vector<foo> vec_f;,则输出将为:

copy ctor
0087C308
move ctor
0087C308
copy ctor
0087C308
move ctor
0087C308

应该是你的期望。

P.S。我正在使用VS2013 Express。