kesalahan: penggunaan fungsi yang dihapus

122

Saya telah mengerjakan beberapa kode C ++ yang telah ditulis seorang teman dan saya mendapatkan kesalahan berikut yang belum pernah saya lihat sebelumnya ketika mengkompilasi dengan gcc4.6:

error: use of deleted function

GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h

Edit: Ini berasal dari bagian kode yang menggunakan boost MSM: Boost Webpage

Sunting2: Tidak ada yang = delete()digunakan di mana pun di kode sumber.

Secara umum, apa arti kesalahan ini? Apa yang harus saya cari ketika jenis kesalahan ini terjadi?

shuttle87
sumber
4
dan kode yang Anda kompilasi?
ColWhi
Saya lebih bertanya-tanya apa artinya kesalahan itu? Apakah saya perlu memposting kode untuk itu juga?
shuttle 87
1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 mungkin membantu, juga apakah Anda menggunakan boost?
ColWhi
@Sasquiha, ya saya menggunakan boost MSM.
Antar
20
Karena ini muncul sebagai kecocokan Google pertama untuk jenis kesalahan ini - bukan kasusnya di sini, tetapi penyebab paling umum untuk jenis kesalahan ini adalah setelah Anda menambahkan beberapa konstruktor khusus ke kelas - akibatnya kompilator berhenti membuat konstruktor default , dan jika sebuah instance dari kelas pernah dibuat melalui konstruktor default, kesalahan ini muncul. Cukup tambahkan konstruktor default secara eksplisit.
SF.

Jawaban:

171

Pesan kesalahan dengan jelas mengatakan bahwa konstruktor default telah dihapus secara implisit . Ia bahkan mengatakan mengapa: kelas berisi variabel const non-statis, yang tidak akan diinisialisasi oleh ctor default.

class X {
    const int x;
};

Karena X::xitu const, itu harus diinisialisasi - tetapi ctor default biasanya tidak menginisialisasi (karena ini adalah tipe POD). Oleh karena itu, untuk mendapatkan ctor default, Anda perlu mendefinisikannya sendiri (dan harus menginisialisasi x). Anda bisa mendapatkan situasi yang sama dengan anggota yang menjadi referensi:

class X { 
    whatever &x;
};

Mungkin perlu dicatat bahwa keduanya juga akan menonaktifkan pembuatan implisit dari operator penugasan, karena alasan yang pada dasarnya sama. Operator penugasan implisit biasanya melakukan penugasan berdasarkan anggota, tetapi dengan anggota const atau anggota referensi, tidak dapat melakukannya karena anggota tersebut tidak dapat ditetapkan. Untuk membuat tugas berfungsi, Anda perlu menulis operator tugas Anda sendiri.

Inilah sebabnya mengapa seorang constanggota biasanya harus statis - ketika Anda melakukan tugas, Anda tetap tidak dapat menetapkan anggota const. Dalam kasus umum, semua instance Anda akan memiliki nilai yang sama sehingga mungkin juga berbagi akses ke satu variabel daripada memiliki banyak salinan variabel yang semuanya akan memiliki nilai yang sama.

Tentu saja dimungkinkan untuk membuat instance dengan nilai yang berbeda - Anda (misalnya) memberikan nilai saat Anda membuat objek, sehingga dua objek yang berbeda dapat memiliki dua nilai yang berbeda. Namun, jika Anda mencoba melakukan sesuatu seperti menukar mereka, anggota const akan mempertahankan nilai aslinya alih-alih ditukar.

Jerry Coffin
sumber
@Jeffry Coffin: Pesan kesalahan sebenarnya telah diposting sebagai edit, Pesan kesalahan awal hanya dipostingC++ error: use of deleted function
Alok Simpan
1
@Als: Maaf, saya mungkin seharusnya secara eksplisit bahwa saya tidak bermaksud itu sebagai penghinaan atau apa pun atas perintah itu, hanya saja apa yang saat ini tersedia menunjukkan bahwa jawaban itu tidak benar.
Jerry Coffin
Tidak masalah, saya tidak bermaksud untuk bersikukuh ... Jawaban Anda luar biasa dan menjelaskan situasinya dengan baik. +1 dari saya :)
Alok Save
Saya berasumsi Anda mungkin dapat membantu saya dengan masalah saya di sini: stackoverflow.com/questions/23349524/…
Saher Ahwal
2
@OllieFord: Itu tergantung. Apa yang akan terjadi jika (misalnya) Anda menetapkan objek dengan satu nilai di bidang itu ke yang lain yang memiliki nilai berbeda di bidang itu? Jika harus ditimpa, maka tidak bisa menjadi const. Jika itu tidak diizinkan sama sekali, maka nilainya mungkin benar-benar merupakan bagian dari tipe (misalnya, parameter template, jika diketahui pada waktu kompilasi).
Jerry Coffin
11

Anda menggunakan fungsi yang ditandai sebagai deleted.
Misalnya:

int doSomething( int ) = delete;

= Delete adalah fitur baru dari C ++ 0x. Ini berarti kompilator harus segera berhenti mengkompilasi dan mengeluh "fungsi ini dihapus" setelah pengguna menggunakan fungsi tersebut.

Jika Anda melihat kesalahan ini, Anda harus memeriksa deklarasi fungsi untuk =delete.

Untuk mengetahui lebih lanjut tentang fitur baru yang diperkenalkan di C ++ 0x, lihat ini .

Alok Save
sumber
7
Karena penasaran, kapan melakukan hal seperti itu bisa membantu?
Pepe
@Peter: untuk mencegah konversi implisit.
R. Martinho Fernandes
7
Sebenarnya dikatakan "dihapus secara implisit karena ..." , contoh di atas akan eksplisit.
Georg Fritzsche
@Peter R: sepertinya ini adalah contoh: en.wikipedia.org/wiki/…
shuttle87
1
@Downvoter: Pesan kesalahan sebenarnya telah diposting sebagai edit, Pesan kesalahan awal hanya dipostingC++ error: use of deleted function
Alok Simpan
4

gcc 4.6 mendukung fitur baru dari fungsi yang dihapus, di mana Anda dapat menulis

hdealt() = delete;

untuk menonaktifkan konstruktor default.

Di sini kompilator jelas melihat bahwa konstruktor default tidak dapat dibuat, dan =deleteitu untuk Anda.

Bo Persson
sumber
2

Saya mengalami kesalahan ini saat mewarisi dari kelas abstrak dan tidak menerapkan semua metode virtual murni di subkelas saya.

Christopher
sumber
1
Demikian pula, saya mendapatkan yang sama dengan berasal public virtualdari kelas dasar tingkat 2 di mana kelas dasar tingkat 1 memiliki konstruktor default yang dihapus secara eksplisit. Menghapus virtualmemperbaiki masalah tanpa harus menerapkan semua metode.
Maitre Bart
1

Dalam standar C ++ 0x saat ini, Anda dapat secara eksplisit menonaktifkan konstruktor default dengan sintaks hapus, misalnya

MyClass() = delete;

Gcc 4.6 adalah versi pertama yang mendukung sintaks ini, jadi mungkin itulah masalahnya ...

jarmond.dll
sumber
Gcc 4.6 is the first version to support this syntaxSaya rasa itu akan menjelaskan mengapa saya belum pernah melihatnya sebelumnya karena saya baru saja mulai menggunakan gcc4.6 baru-baru ini.
shuttle87
2
Saya telah menggunakan sintaks ini dengan GCC 4.5 selama bertahun-tahun. Maksudku hari.
R. Martinho Fernandes
Ah, saya pasti sedang memikirkan para pemberi tugas yang ada di GCC 4.6.
jarmond
1

Beralih dari gcc 4.6 ke gcc 4.8 menyelesaikan masalah ini untuk saya.

Michael Bosworth
sumber