Saya agak bingung tentang perbedaan antara push_back
dan emplace_back
.
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
Karena ada push_back
kelebihan mengambil referensi nilai saya tidak cukup melihat apa tujuan emplace_back
menjadi?
template <class _Valty> void emplace_back(_Valty&& _Val)
versi yang mengambil referensi universal yang menyediakan penerusan yang sempurna untukexplicit
konstruktor argumen tunggal.push_back
yang lebih disukaiemplace_back
? Satu-satunya kasus yang dapat saya pikirkan adalah jika suatu kelas entah bagaimana dapat disalin (T&operator=(constT&)
) tetapi tidak dapat dikonstruksikan (T(constT&)
), tetapi saya tidak dapat memikirkan mengapa orang menginginkannya.Jawaban:
Selain apa yang dikatakan pengunjung:
Fungsi yang
void emplace_back(Type&& _Val)
disediakan oleh MSCV10 tidak sesuai dan mubazir, karena seperti yang Anda catat, ini setara denganpush_back(Type&& _Val)
.Tapi bentuk nyata C ++ 0x
emplace_back
sangat bergunavoid emplace_back(Args&&...)
:;Alih-alih mengambil
value_type
itu membutuhkan daftar argumen variadik, sehingga itu berarti bahwa Anda sekarang dapat dengan sempurna meneruskan argumen dan membangun langsung objek ke wadah tanpa sementara sama sekali.Itu berguna karena tidak peduli seberapa banyak kepintaran RVO dan memindahkan semantik ke meja, masih ada kasus rumit di mana push_back cenderung membuat salinan yang tidak perlu (atau memindahkan). Misalnya, dengan
insert()
fungsi tradisional astd::map
, Anda harus membuat sementara, yang kemudian akan disalin kestd::pair<Key, Value>
, yang kemudian akan disalin ke peta:Jadi mengapa mereka tidak mengimplementasikan versi emplace_back yang tepat di MSVC? Sebenarnya, itu menyadap saya beberapa waktu yang lalu, jadi saya mengajukan pertanyaan yang sama di blog Visual C ++ . Berikut adalah jawaban dari Stephan T Lavavej, pengelola resmi implementasi perpustakaan standar Visual C ++ di Microsoft.
Itu keputusan yang bisa dimengerti. Setiap orang yang mencoba sekali saja untuk meniru template variadic dengan trik mengerikan preprocessor tahu betapa menjijikkannya hal ini.
sumber
pair<const int,Complicated>
tidak memiliki konstruktor yang mengambil int, int lain, parameter ganda dan sebagai string ke-4. Namun, Anda bisa langsung membangun objek pasangan ini menggunakan konstruktor piecewise-nya. Sintaksnya akan berbeda, tentu saja:m.emplace(std::piecewise,std::forward_as_tuple(4),std::forward_as_tuple(anInt,aDouble,aString));
emplace_back
selama itu diterapkan ke dalam Visual C ++ ketika templat variadic ditambahkan: msdn.microsoft.com/en-us/library/hh567368. aspxemplace_back
tidak boleh mengambil argumen tipevector::value_type
, melainkan argumen variadik yang diteruskan ke konstruktor item terlampir.Dimungkinkan untuk meneruskan
value_type
yang akan diteruskan ke copy constructor.Karena ini meneruskan argumen, ini berarti bahwa jika Anda tidak memiliki nilai, ini masih berarti bahwa wadah akan menyimpan salinan yang "disalin", bukan salinan yang dipindahkan.
Tetapi hal di atas harus identik dengan apa yang
push_back
dilakukannya. Ini mungkin lebih dimaksudkan untuk kasus penggunaan seperti:sumber
s
lingkup bergerak , bukankah itu berbahaya?vec.emplace_back("Hello")
akan berfungsi, karenaconst char*
argumen akan diteruskan kestring
konstruktor. Inilah inti dariemplace_back
.std::vector
. Kosongstd::vector
adalah keadaan yang valid, tetapi Anda tidak dapat memanggilnyafront()
. Ini berarti bahwa setiap fungsi yang tidak memiliki prasyarat masih dapat dipanggil (dan destruktor tidak akan pernah memiliki prasyarat).Optimasi untuk
emplace_back
dapat ditunjukkan dalam contoh berikut.Untuk
emplace_back
konstruktorA (int x_arg)
akan dipanggil. Dan untukpush_back
A (int x_arg)
disebut pertama danmove A (A &&rhs)
sesudahnya disebut.Tentu saja, konstruktor harus ditandai sebagai
explicit
, tetapi untuk contoh saat ini baik untuk menghilangkan kesaksian.keluaran:
sumber
emplace_back
vspush_back
.v.emplace_back(x);
x yang secara eksplisit move-constructable tetapi hanya secara eksplisit copy-constructable. Fakta yangemplace_back
"tersirat" eksplisit membuat saya berpikir bahwa fungsi masuk saya untuk menambahkan mungkin seharusnyapush_back
. Pikiran?a.emplace_back
kedua kalinya, konstruktor pemindahan akan dipanggil!Kode yang bagus untuk push_back dan emplace_back ditampilkan di sini.
http://en.cppreference.com/w/cpp/container/vector/emplace_back
Anda dapat melihat operasi pemindahan pada push_back dan bukan pada emplace_back.
sumber
emplace_back
implementasi yang sesuai akan meneruskan argumen kevector<Object>::value_type
konstruktor ketika ditambahkan ke vektor. Saya ingat Visual Studio tidak mendukung templat variadic, tetapi dengan templat variadic akan didukung di Visual Studio 2013 RC, jadi saya kira tanda tangan yang sesuai akan ditambahkan.Dengan
emplace_back
, jika Anda meneruskan argumen secara langsung kevector<Object>::value_type
konstruktor, Anda tidak perlu tipe yang dapat dipindahkan atau disalin untukemplace_back
fungsi, secara tegas. Dalamvector<NonCopyableNonMovableObject>
hal ini, ini tidak berguna, karenavector<Object>::value_type
perlu jenis yang dapat disalin atau bergerak untuk tumbuh.Tetapi perhatikan bahwa ini bisa berguna untuk
std::map<Key, NonCopyableNonMovableObject>
, karena begitu Anda mengalokasikan entri di peta, itu tidak perlu dipindahkan atau disalin lagi, tidak seperti denganvector
, yang berarti bahwa Anda dapat menggunakanstd::map
secara efektif dengan tipe yang dipetakan yang tidak dapat disalin maupun bergerak.sumber
Satu lagi dalam hal daftar:
sumber
Kasus penggunaan khusus untuk
emplace_back
: Jika Anda perlu membuat objek sementara yang kemudian akan didorong ke dalam wadah, gunakanemplace_back
sebagai gantipush_back
. Ini akan membuat objek di tempat di dalam wadah.Catatan:
push_back
dalam kasus di atas akan membuat objek sementara dan memindahkannya ke wadah. Namun, konstruksi di tempat yang digunakanemplace_back
akan lebih berkinerja daripada membangun dan kemudian memindahkan objek (yang umumnya melibatkan penyalinan).emplace_back
alih-alihpush_back
dalam semua kasus tanpa banyak masalah. (Lihat pengecualian )sumber