Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah C 11 Move Constructor Tidak Dipanggil Apabila Objek Sementara Digunakan untuk Memulakan Objek Lain?

Mengapakah C 11 Move Constructor Tidak Dipanggil Apabila Objek Sementara Digunakan untuk Memulakan Objek Lain?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-11-05 05:06:02946semak imbas

Why is the C  11 Move Constructor Not Called When a Temporary Object is Used to Initialize Another Object?

C 11 Move Constructor Not Called, Default Constructor Preferred

Penerangan:
Apabila bekerja dengan move semantik dalam C 11, ia mungkin untuk menghadapi senario di mana pembina bergerak secara tidak dijangka dilangkau memihak kepada pembina lalai. Artikel ini meneroka isu ini, mengkaji sebab asas dan menyediakan penyelesaian.

Masalah:
Pertimbangkan kelas X berikut dengan pembina yang mengeluarkan mesej:

<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>

Dalam penggunaan sampel yang disediakan di bawah, kami mencipta tiga objek:

<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>

Walau bagaimanapun, bukannya output yang dijangka menunjukkan pembina bergerak dipanggil untuk z, sebaliknya pembina lalai digunakan.

Penjelasan Gelagat:
Tingkah laku yang diperhatikan adalah disebabkan oleh pengoptimuman pengkompil yang dipanggil

penyingkiran salinan. C 11 membenarkan penyusun untuk meninggalkan penyalinan/menggerakkan objek dalam situasi tertentu untuk meningkatkan prestasi. Salah satu daripada situasi ini ialah apabila objek sementara akan disalin/dialihkan ke objek dengan jenis cv-tidak layak yang sama.
Dalam baris terakhir kod sampel kami, X("ujian") mencipta X sementara objek dan ia mempunyai jenis cv-tidak layak yang sama seperti sasaran (z). Oleh itu, pengkompil dibenarkan untuk mengenepikan salinan dan memindahkan pembina, membina objek sementara secara langsung ke dalam z tanpa menggunakan salah satu pembina.

Penyelesaian:

Untuk memaksa pembina bergerak menjadi dipanggil, kita boleh menggunakan std::move() untuk menunjukkan secara jelas bahawa perpindahan harus dilakukan:

Dengan pengubahsuaian ini, output yang dijangkakan dihasilkan, mengesahkan penglibatan pembina bergerak.

Atas ialah kandungan terperinci Mengapakah C 11 Move Constructor Tidak Dipanggil Apabila Objek Sementara Digunakan untuk Memulakan Objek Lain?. 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