初始化列表和移动构造函数

时间:2012-12-14 14:38:10

标签: c++ c++11 move initializer-list

  

可能重复:
  initializer_list and move semantics

在以下示例中,即使发出临时对象,也会最终执行复制:

// test.cpp

#include <iostream>
#include <vector>
#include <utility>
#include <initializer_list>

using namespace std;

class mystr : public string
{
public:
    mystr() = default;
    mystr(const char* c) : string(c) { }

    mystr(mystr& m) : string(m) { cout << "& " << c_str() << endl; }
    mystr(mystr const & m) : string(m) { cout << "const & " << c_str() << endl; }
    mystr(mystr&& m) : string(move(m)) { cout << "&& " << c_str() << endl; }
};

class myvector
{
public:
    myvector(initializer_list<mystr> i)
    {
        cout << "Inside constructor" << endl;

        v = vector<mystr>(i);
    }

private:
    vector<mystr> v;
};

int main()
{
    mystr a("hello");

    myvector v{ a, mystr("bye"), a, mystr("sorry") };
}

输出:

$ g++ --version | grep "g++"
g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
$ g++ -std=c++11 test.cpp
$ ./a.out
& hello
& hello
Inside constructor
const & hello
const & bye
const & hello
const & sorry

复制“命名”对象并省略临时对象,但是,一旦构造初始化列表,就会在其他时间复制所有元素:初始化列表删除了对象原始性质的信息。使用-fno-elide-constructors,这个过程更容易理解:

$ g++ -std=c++11 -fno-elide-constructors test.cpp
$ ./a.out
& hello
&& hello
&& bye
&& bye
& hello
&& hello
&& sorry
&& sorry
Inside constructor
const & hello
const & bye
const & hello
const & sorry

临时对象被移动两次,持久对象在到达构造函数之前被复制和移动,这意味着,在创建初始化列表的过程中。一旦进入构造函数,列表中的所有对象都是构造函数的持久性,因此,它们都被复制了。

是否可以避免此行为(转发)?

我认为,容器应该始终将对象(而不是复制)从初始化列表移动到它自己的容器,因为在构建初始化列表时,对象已经被复制了一次。为什么要连续两次复制?

0 个答案:

没有答案