Apa arti "default" setelah deklarasi fungsi kelas?


221

Saya telah melihat defaultdigunakan di sebelah fungsi deklarasi di kelas. Apa fungsinya?

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};

26
Apa yang dilakukan "&" yang mendahului "=" dalam deklarasi operator penugasan?
dshin

6
@dshin Ini adalah kualifikasi ulang fungsi anggota .
Kane

Jawaban:


249

Ini adalah fitur C ++ 11 yang baru .

Itu berarti bahwa Anda ingin menggunakan versi yang dihasilkan kompiler dari fungsi itu, jadi Anda tidak perlu menentukan tubuh.

Anda juga dapat menggunakan = deleteuntuk menentukan bahwa Anda tidak ingin kompiler membuat fungsi itu secara otomatis.

Dengan diperkenalkannya konstruktor pemindahan dan pemindahan operator penugasan, aturan untuk kapan versi otomatis pembangun, pemantik dan operator penugasan dihasilkan telah menjadi sangat kompleks. Menggunakan = defaultdan = deletemembuat segalanya lebih mudah karena Anda tidak perlu mengingat aturan: Anda hanya mengatakan apa yang Anda inginkan terjadi.


17
= deletelebih kuat: Artinya, menggunakan fungsi itu dilarang, meskipun masih mengambil bagian dalam resolusi kelebihan.
Deduplicator

2
Tetapi, jika kita ingin menggunakan definisi penghasil kompiler, maka tidakkah kita harus lewati menulis fungsi itu alih-alih "pertama menulisnya dan kemudian menetapkannya ke default"?
Mayank Jindal

47

Ini adalah fitur C ++ 0x baru yang memberi tahu kompiler untuk membuat versi default dari masing-masing konstruktor atau operator penugasan, yaitu yang hanya melakukan penyalinan atau memindahkan tindakan untuk setiap anggota. Ini berguna karena move constructor tidak selalu dihasilkan secara default (misalnya jika Anda memiliki custom destructor), tidak seperti copy constructor (dan juga untuk penugasan), tetapi jika tidak ada yang non-sepele untuk ditulis, lebih baik membiarkan kompiler menanganinya daripada mengeja sendiri setiap kali.

Perhatikan juga bahwa konstruktor default tidak akan dihasilkan jika Anda memberikan konstruktor non-standar lainnya. Jika Anda masih menginginkan konstruktor default juga, Anda dapat menggunakan sintaks ini untuk membuat kompiler membuatnya.

Sebagai kasus penggunaan lain, ada beberapa situasi di mana konstruktor salinan tidak akan dihasilkan secara implisit (misalnya jika Anda memberikan konstruktor pemindahan kustom). Jika Anda masih menginginkan versi default, Anda dapat memintanya dengan sintaks ini.

Lihat Bagian 12.8 dari standar untuk perincian.


5
Meskipun tidak hanya untuk konstruktor dan tugas, tetapi juga berlaku untuk operator new/new[], operator delete/delete[]dan kelebihannya.
Sebastian Mach

21

Ini baru dalam C ++ 11, lihat di sini . Ini bisa sangat berguna jika Anda telah mendefinisikan satu konstruktor, tetapi ingin menggunakan default untuk yang lain. Pra-C ++ 11 Anda harus mendefinisikan semua konstruktor setelah menetapkannya, bahkan jika mereka setara dengan default.

Juga perhatikan bahwa dalam situasi tertentu tidak mungkin untuk memberikan konstruktor default yang ditetapkan pengguna yang berperilaku sama dengan kompilator yang disintesis di bawah default dan inisialisasi nilai . defaultmemungkinkan Anda untuk mendapatkan perilaku itu kembali.


5
mengenai paragraf kedua, dapatkah Anda memberikan contoh?
John Smith

11

Kasus penggunaan lain yang saya tidak lihat disebutkan dalam jawaban ini adalah bahwa hal itu dengan mudah memungkinkan Anda untuk mengubah visibilitas konstruktor. Sebagai contoh, mungkin Anda ingin kelas teman dapat mengakses copy constructor, tetapi Anda tidak ingin itu tersedia untuk umum.


1

C ++ 17 N4659 konsep standar

https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Fungsi yang secara eksplisit-default":

1 Definisi fungsi dari bentuk:

attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;

disebut definisi eksplisit-standar. Suatu fungsi yang secara eksplisit default harus

  • (1.1) - menjadi fungsi anggota khusus,

  • (1.2) - memiliki tipe fungsi yang dideklarasikan sama (kecuali untuk kemungkinan ref-kualifikasi yang berbeda dan kecuali bahwa dalam kasus copy constructor atau operator penugasan copy, tipe parameter dapat “merujuk ke non-const T”, di mana T adalah nama kelas fungsi anggota) seolah-olah telah dinyatakan secara implisit, dan

  • (1.3) - tidak memiliki argumen default.

2 Fungsi eksplisit-standar yang tidak didefinisikan sebagai dihapus dapat dideklarasikan hanya dengan constexpr jika secara implisit dinyatakan sebagai constexpr. Jika suatu fungsi secara eksplisit default pada deklarasi pertama, itu secara implisit dianggap sebagai constexpr jika deklarasi implisit akan.

3 Jika suatu fungsi yang secara eksplisit default dinyatakan dengan noexcept-specifier yang tidak menghasilkan spesifikasi eksepsi yang sama dengan deklarasi implisit (18.4), maka

  • (3.1) - jika fungsi secara eksplisit default pada deklarasi pertamanya, itu didefinisikan sebagai dihapus;

  • (3.2) - jika tidak, program ini cacat.

4 [Contoh:

struct S {
  constexpr S() = default;            // ill-formed: implicit S() is not constexpr
  S(int a = 0) = default;             // ill-formed: default argument
  void operator=(const S&) = default; // ill-formed: non-matching return type
  ~ S() noexcept(false) = default;    // deleted: exception specification does not match
private:
  int i;                              // OK: private copy constructor
  S(S&);
};
S::S(S&) = default;                   // OK: defines copy constructor

- contoh akhir]

5 Fungsi-fungsi yang secara eksplisit-default dan fungsi-fungsi yang dinyatakan secara implisit secara kolektif disebut fungsi-fungsi yang gagal, dan implementasinya harus memberikan definisi implisit untuk mereka (15.1 15.4, 15.8), yang mungkin berarti mendefinisikannya sebagai dihapus. Suatu fungsi disediakan pengguna jika dideklarasikan oleh pengguna dan tidak secara default dihapus atau dihapus pada deklarasi pertamanya. Fungsi yang disediakan pengguna secara default-default (yaitu, secara eksplisit default setelah deklarasi pertama) didefinisikan pada titik di mana ia secara eksplisit default; jika fungsi seperti itu secara implisit didefinisikan sebagai dihapus, program tersebut salah bentuk. [Catatan: Mendeklarasikan fungsi sebagai default setelah deklarasi pertama dapat memberikan eksekusi yang efisien dan definisi ringkas sambil mengaktifkan antarmuka biner yang stabil ke basis kode yang berkembang. - catatan akhir]

6 [Contoh:

struct trivial {
  trivial() = default;
  trivial(const trivial&) = default;
  trivial(trivial&&) = default;
  trivial& operator=(const trivial&) = default;
  trivial& operator=(trivial&&) = default;
  ~ trivial() = default;
};
struct nontrivial1 {
  nontrivial1();
};
nontrivial1::nontrivial1() = default;       // not first declaration

- contoh akhir]

Maka pertanyaannya tentu saja fungsi mana yang dapat dinyatakan secara implisit dan kapan itu terjadi, yang telah saya jelaskan di:

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.