Kami sekarang memiliki C ++ 11 dengan banyak fitur baru. Yang menarik dan membingungkan (setidaknya bagi saya) adalah yang baru nullptr
.
Yah, tidak perlu lagi untuk makro jahat NULL
.
int* x = nullptr;
myclass* obj = nullptr;
Tetap saja, saya tidak mengerti cara nullptr
kerjanya. Sebagai contoh, artikel Wikipedia mengatakan:
C ++ 11 memperbaiki ini dengan memperkenalkan kata kunci baru untuk dijadikan sebagai konstanta penunjuk nol yang dibedakan: nullptr. Ini adalah tipe nullptr_t , yang secara implisit dapat dikonversi dan sebanding dengan tipe penunjuk atau tipe penunjuk-ke-anggota. Ini tidak secara implisit dapat dikonversi atau sebanding dengan tipe integral, kecuali untuk bool.
Bagaimana kata kunci dan turunan tipe?
Juga, apakah Anda memiliki contoh lain (di samping Wikipedia) di mana nullptr
lebih baik dari yang lama 0
?
nullptr
juga digunakan untuk mewakili referensi nol untuk handle yang dikelola di C ++ / CLI.nullptr_t
dijamin hanya memiliki satu anggotanullptr
,? Jadi, jika suatu fungsi dikembalikannullptr_t
, maka kompiler sudah tahu nilai mana yang akan dikembalikan, terlepas dari isi fungsinya?std::nullptr_t
dapat dipakai, tetapi semua instance akan identik dengannullptr
karena jenisnya didefinisikan sebagaitypedef decltype(nullptr) nullptr_t
. Saya percaya alasan utama tipe ini ada adalah agar fungsi dapat kelebihan beban untuk ditangkapnullptr
, jika perlu. Lihat di sini untuk contoh.Jawaban:
Ini tidak mengejutkan. Kedua
true
danfalse
adalah kata kunci dan sebagai literal mereka memiliki tipe (bool
).nullptr
adalah pointer tipe literalstd::nullptr_t
, dan ini merupakan nilai awal (Anda tidak dapat menggunakan alamatnya&
).4.10
tentang konversi penunjuk mengatakan bahwa nilai jenisstd::nullptr_t
adalah konstanta penunjuk nol, dan konstanta penunjuk nol integral dapat dikonversi menjadistd::nullptr_t
. Arah sebaliknya tidak diizinkan. Ini memungkinkan overloading fungsi untuk pointer dan integer, dan meneruskannullptr
untuk memilih versi pointer. LulusNULL
atau0
akan bingung memilihint
versi.Sebuah gips
nullptr_t
untuk tipe integral membutuhkan areinterpret_cast
, dan memiliki semantik yang sama dengan gips(void*)0
untuk tipe integral (implementasi pemetaan didefinisikan). Areinterpret_cast
tidak dapat dikonversinullptr_t
ke tipe pointer apa pun. Andalkan konversi implisit jika memungkinkan atau gunakanstatic_cast
.Standar mengharuskan
sizeof(nullptr_t)
besizeof(void*)
.sumber
cond ? nullptr : 0;
. Dihapus dari jawaban saya.NULL
bahkan tidak dijamin0
. Bisa jadi0L
, dalam hal ini panggilan kevoid f(int); void f(char *);
akan ambigu.nullptr
akan selalu mendukung versi penunjuk, dan tidak pernah memanggil yangint
satu. Perhatikan juga bahwanullptr
dapat dikonversi kebool
(konsep mengatakan bahwa di4.12
).int
versi. Tapif(0L)
ambigu, karenalong -> int
juga sebagailong -> void*
adalah keduanya sama-sama mahal. Jadi jika NULL ada0L
di kompiler Anda, maka panggilanf(NULL)
akan ambigu mengingat dua fungsi tersebut. Tidak demikian halnya dengannullptr
tentu saja.(void*)0
dalam C ++. Tapi itu dapat didefinisikan sebagai sembarang pointer nol konstan, yang merupakan konstanta integral dengan nilai 0 dannullptr
memenuhi. Jadi, pasti tidak akan tetapi bisa . (Kamu lupa ping saya btw ..)Dari nullptr: Tipe-aman dan Clear-Cut Null Pointer :
Referensi lain:
template
sumber
Mengapa nullptr di C ++ 11? Apa itu? Mengapa NULL tidak cukup?
Pakar C ++ Alex Allain mengatakannya dengan sempurna di sini (penekanan saya ditambahkan dengan huruf tebal):
Allain mengakhiri artikelnya dengan:
(Kata-kataku):
Terakhir, jangan lupa bahwa itu
nullptr
adalah objek - kelas. Itu dapat digunakan di mana sajaNULL
digunakan sebelumnya, tetapi jika Anda memerlukan jenisnya untuk beberapa alasan, jenisnya dapat diekstraksi dengandecltype(nullptr)
, atau langsung digambarkan sebagaistd::nullptr_t
, yang hanya merupakantypedef
daridecltype(nullptr)
.Referensi:
sumber
Ketika Anda memiliki fungsi yang dapat menerima pointer ke lebih dari satu jenis, memanggilnya dengan
NULL
ambigu. Cara ini dikerjakan sekarang sangat berantakan dengan menerima int dan menganggapnyaNULL
.Di dalam
C++11
Anda akan dapat kelebihan padanullptr_t
sehinggaptr<T> p(42);
akan menjadi kesalahan waktu kompilasi daripada run-timeassert
.sumber
NULL
didefinisikan sebagai0L
?nullptr
tidak dapat ditugaskan ke tipe integral sepertiint
tetapi hanya tipe pointer; baik tipe built-in pointer sepertiint *ptr
atau smart pointer sepertistd::shared_ptr<T>
Saya percaya ini adalah perbedaan penting karena
NULL
masih dapat ditugaskan untuk kedua tipe integral dan pointer sebagaimanaNULL
makro diperluas0
yang dapat berfungsi sebagai nilai awal untukint
serta pointer.sumber
NULL
tidak dijamin akan diperluas ke0
.Iya. Ini juga contoh dunia nyata (disederhanakan) yang terjadi dalam kode produksi kami. Itu hanya menonjol karena gcc mampu mengeluarkan peringatan ketika crosscompiling ke platform dengan lebar register yang berbeda (masih tidak yakin persis mengapa hanya ketika crosscompiling dari x86_64 ke x86, ingatkan
warning: converting to non-pointer type 'int' from NULL
):Pertimbangkan kode ini (C ++ 03):
Ini menghasilkan output ini:
sumber
Nah, bahasa lain telah memesan kata-kata yang merupakan contoh jenis. Python, misalnya:
Ini sebenarnya perbandingan yang cukup dekat karena
None
biasanya digunakan untuk sesuatu yang belum diinternisasi, tetapi pada saat yang sama perbandingan sepertiNone == 0
itu salah.Di sisi lain, di dataran C,
NULL == 0
akan mengembalikan true IIRC karenaNULL
hanya makro mengembalikan 0, yang selalu merupakan alamat tidak valid (AFAIK).sumber
NULL
adalah makro yang mengembang ke nol, konstanta pelempar nol ke pointer menghasilkan pointer nol. Pointer nol tidak harus nol (tetapi sering), nol tidak selalu merupakan alamat yang tidak valid, dan nol yang tidak konstan untuk sebuah pointer tidak harus nol, dan pointer nol dilemparkan ke bilangan bulat tidak harus nol. Saya harap saya bisa melakukan itu tanpa melupakan apa pun. Referensi: c-faq.com/null/null2.htmlItu adalah kata kunci karena standar akan menentukannya seperti itu. ;-) Menurut konsep publik terbaru (n2914)
Ini berguna karena tidak secara implisit dikonversi ke nilai integral.
sumber
Katakanlah Anda memiliki fungsi (f) yang kelebihan beban untuk mengambil int dan char *. Sebelum C ++ 11, Jika Anda ingin menyebutnya dengan pointer nol, dan Anda menggunakan NULL (yaitu nilai 0), maka Anda akan memanggil yang kelebihan beban untuk int:
Ini mungkin bukan yang Anda inginkan. C ++ 11 memecahkan ini dengan nullptr; Sekarang Anda dapat menulis yang berikut ini:
sumber
Biarkan saya memberi Anda implementasi tidak canggih
nullptr_t
nullptr
adalah contoh halus dari idiom Return Type Resolver untuk secara otomatis menyimpulkan pointer nol dari tipe yang benar tergantung pada jenis instance yang ditugaskan kepadanya.nullptr
sedang ditugaskan ke pointer integer,int
jenis instantiation dari fungsi konversi templatized dibuat. Dan hal yang sama juga berlaku untuk pointer metode.nullptr
bilangan bulat integer dengan nilai nol, Anda tidak dapat menggunakan alamatnya yang kami capai dengan menghapus & operator.Mengapa kita perlu
nullptr
di tempat pertama?NULL
memiliki beberapa masalah dengan itu seperti di bawah ini:1️⃣ Konversi tersirat
2️⃣ Fungsi memanggil ambiguitas
3️⃣ Konstruktor kelebihan beban
String s((char*)0))
.sumber
0 digunakan sebagai satu-satunya nilai integer yang dapat digunakan sebagai inisialisasi bebas-cor untuk pointer: Anda tidak dapat menginisialisasi pointer dengan nilai integer lain tanpa gips. Anda dapat menganggap 0 sebagai singleton consexpr secara sintaksis mirip dengan integer literal. Itu dapat memulai setiap pointer atau integer. Tetapi yang mengejutkan, Anda akan menemukan bahwa itu tidak memiliki tipe yang berbeda: itu adalah
int
. Jadi, mengapa 0 dapat menginisialisasi pointer dan 1 tidak bisa? Jawaban praktisnya adalah kita perlu sarana untuk mendefinisikan nilai null pointer dan konversi implisit langsungint
ke pointer rentan kesalahan. Jadi 0 menjadi makhluk aneh aneh yang aneh dari era prasejarah.nullptr
diusulkan menjadi representasi constexpr tunggal nyata dari nilai nol untuk menginisialisasi pointer. Itu tidak dapat digunakan untuk secara langsung menginisialisasi bilangan bulat dan menghilangkan ambiguitas yang terlibat dengan mendefinisikanNULL
dalam hal 0.nullptr
dapat didefinisikan sebagai perpustakaan menggunakan sintaks std tetapi secara semantik tampak menjadi komponen inti yang hilang.NULL
sekarang tidak digunakan laginullptr
, kecuali beberapa perpustakaan memutuskan untuk mendefinisikannya sebagainullptr
.sumber
Inilah tajuk LLVM.
(Banyak yang bisa diungkap dengan cepat
grep -r /usr/include/*`
)Satu hal yang melompat keluar adalah
*
kelebihan operator (mengembalikan 0 jauh lebih ramah daripada segfaulting ...). Hal lain adalah tidak terlihat kompatibel dengan menyimpan alamat sama sekali . Yang, dibandingkan dengan bagaimana cara slinging void * dan memberikan hasil NULL ke pointer normal sebagai nilai sentinel, jelas akan mengurangi faktor "jangan lupa, itu mungkin bom".sumber
NULL tidak perlu 0. Selama Anda menggunakan selalu NULL dan tidak pernah 0, NULL dapat berupa nilai apa pun. Dengan asumsi Anda memprogram Mikrokontroler von Neuman dengan memori datar, yang memiliki vektor interruptnya pada 0. Jika NULL adalah 0 dan sesuatu menulis pada NULL Pointer maka Mikrokontroler mogok. Jika NULL misalkan 1024 dan pada 1024 ada variabel yang dilindungi undang-undang, maka penulisan tidak akan merusaknya, dan Anda dapat mendeteksi penetapan NULL Pointer dari dalam program. Ini tidak ada gunanya pada PC, tetapi untuk pesawat ruang angkasa, peralatan militer atau medis, penting untuk tidak menabrak.
sumber