Rumah > Artikel > pembangunan bahagian belakang > Mengapakah Move Constructor Tidak Dipanggil dalam C 11 Apabila Penyingkiran Salin Didayakan?
C 11 Move Constructor Not Called, Default Constructor Preferred
Apabila bekerja dengan kelas dalam C , dijangkakan bahawa move constructor akan digunakan untuk pemindahan sumber yang cekap. Walau bagaimanapun, dalam sesetengah kes, pembina lalai mungkin dipilih secara tidak dijangka.
Pernyataan Masalah
Pertimbangkan kelas berikut:
<code class="cpp">class X { public: explicit X(char* c) { cout << "ctor" << endl; init(c); } X(X& lv) { cout << "copy" << endl; init(lv.c_); } X(X&& rv) { cout << "move" << endl; c_ = rv.c_; rv.c_ = nullptr; } const char* c() { return c_; } private: void init(char* c) { c_ = new char[strlen(c) + 1]; strcpy(c_, c); } char* c_; };</code>
Dengan penggunaan sampel:
<code class="cpp">X x("test"); cout << x.c() << endl; X y(x); cout << y.c() << endl; X z(X("test")); cout << z.c() << endl;</code>
Keluaran yang dijangkakan ialah:
ctor test copy test ctor move test
Walau bagaimanapun, baris terakhir secara tidak dijangka mengeluarkan "ctor" dan bukannya "move."
Penjelasan
Mengikut piawaian C 11, pembina bergerak harus dipanggil dalam situasi tertentu. Dalam kes ini, pergerakan harus berlaku apabila membina z dengan X("ujian"). Walau bagaimanapun, pembina lalai dipanggil sebaliknya.
Tingkah laku ini disebabkan oleh penyingkiran salinan, teknik pengoptimuman yang membolehkan pengkompil membina secara langsung sementara ke dalam sasaran tanpa melakukan operasi salinan atau pemindahan. Pengoptimuman ini digunakan dalam kes di mana pengkompil menentukan bahawa operasi salin/pindah adalah tidak diperlukan dan boleh dihapuskan.
Dalam senario yang diberikan, pengkompil menganggap X("ujian") sementara sebagai calon untuk penghapusan salinan, kerana ia dicipta dan dimusnahkan secara automatik dalam ungkapan yang sama. Akibatnya, ia mengetepikan operasi bergerak dan membina z secara langsung menggunakan data sementara, mengakibatkan panggilan kepada pembina lalai.
Kesimpulan
Penyingkiran salin boleh membawa kepada yang tidak dijangka tingkah laku apabila bekerja dengan pembina bergerak, kerana ia boleh menghalang pembina bergerak daripada digunakan dalam situasi di mana ia dijangka. Penyusun boleh menggunakan penyingkiran salinan berdasarkan heuristik pengoptimuman mereka, yang boleh berbeza-beza antara penyusun dan tetapan pengoptimuman. Adalah penting untuk mengetahui penyingkiran salinan dan potensi kesannya terhadap tingkah laku program.
Atas ialah kandungan terperinci Mengapakah Move Constructor Tidak Dipanggil dalam C 11 Apabila Penyingkiran Salin Didayakan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!