次の例では、一時オブジェクトが送信されても最終的にコピーが実行されます。
// 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
一時オブジェクトは 2 回移動され、永続オブジェクトはコンストラクターに到達する前に、つまりイニシャライザー リストを作成するプロセスでコピーおよび移動されます。コンストラクターに入ると、リスト内のすべてのオブジェクトはコンストラクターの観点からは永続的であるため、それらはすべてコピーされます。
この動作 (転送) を回避することは可能ですか?
イニシャライザリストが構築されるときにオブジェクトがすでに一度コピーされているため、コンテナは常にオブジェクトをイニシャライザリストから独自のコンテナに移動する必要があります(コピーしないでください)。なぜ 2 回連続してコピーするのですか?