Rumah >pembangunan bahagian belakang >C++ >Mengapakah Move Constructor Tidak Dipanggil dalam C 11 Apabila Penyingkiran Salin Didayakan?

Mengapakah Move Constructor Tidak Dipanggil dalam C 11 Apabila Penyingkiran Salin Didayakan?

DDD
DDDasal
2024-11-06 09:46:02309semak imbas

Why Is the Move Constructor Not Called in C  11 When Copy Elision Is Enabled?

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn