Mengapa tidak menghapus setel pointer ke NULL?

127

Saya selalu bertanya-tanya mengapa pengaturan otomatis pointer ke NULL setelah delete bukan bagian dari standar. Jika ini ditangani maka banyak dari crash karena pointer yang tidak valid tidak akan terjadi. Tetapi setelah mengatakan bahwa saya dapat memikirkan beberapa alasan mengapa standar akan membatasi ini:

  1. Kinerja:

    Instruksi tambahan dapat memperlambat deletekinerja.

  2. Mungkinkah karena constpetunjuk.

    Kemudian standar lagi bisa melakukan sesuatu untuk kasus khusus ini kurasa.

Adakah yang tahu alasan pasti untuk tidak mengizinkan ini?

aJ.
sumber

Jawaban:

150

Stroustrup sendiri menjawab. Kutipan:

C ++ secara eksplisit memungkinkan implementasi delete ke nol operan nilai tinggi, dan saya berharap implementasi akan melakukan itu, tetapi ide itu tampaknya tidak menjadi populer dengan pelaksana.

Tetapi masalah utama yang ia kemukakan adalah bahwa argumen delete tidak perlu menjadi nilai.

Dan Olson
sumber
Saya pikir ini bisa menggunakan penjelasan lebih lanjut. Aku bahkan tidak yakin apa yang dia katakan ... Kurasa aku harus kembali lagi nanti ketika aku bisa mendedikasikan beberapa jam untuk meneliti ini sampai aku mengerti. Atau, Anda bisa menguraikan jawaban untuk membantu kami memahami lebih cepat.
Gabriel Staples
63

Pertama, pengaturan ke null akan membutuhkan variabel yang tersimpan dalam memori. Memang benar, bahwa Anda biasanya memiliki pointer di variabel tetapi kadang-kadang Anda mungkin ingin menghapus objek di alamat yang baru dihitung. Itu tidak mungkin dengan penghapusan "nullifying".

Lalu datanglah kinerja. Anda mungkin memiliki kode tertulis sedemikian rupa sehingga pointer akan keluar dari ruang lingkup segera setelah penghapusan selesai. Mengisi itu dengan nol hanyalah buang-buang waktu. Dan C ++ adalah bahasa dengan ideologi "tidak membutuhkannya? Maka Anda tidak perlu membayar untuk itu".

Jika Anda membutuhkan keamanan, ada berbagai petunjuk cerdas di layanan Anda atau Anda dapat menulis sendiri - lebih baik dan lebih cerdas.

sharptooth
sumber
4
Good point wrt dihitung alamat, bahkan jika itu adalah sesuatu yang tidak sering Anda lihat
snemarch
Apakah Anda berbicara tentang penempatan baru ketika Anda mengatakan bahwa kadang-kadang Anda mungkin ingin menghapus objek pada alamat yang baru dihitung. ???
Destructor
@PravasiMeet Tidak, maksud saya sesuatu sepertidelete (ptr + i)
sharptooth
39

Anda dapat memiliki banyak pointer yang menunjuk ke memori itu. Ini akan menciptakan rasa aman yang salah jika pointer yang Anda tentukan untuk penghapusan diatur ke nol, tetapi semua pointer lainnya tidak. Pointer tidak lebih dari sebuah alamat, sebuah angka. Mungkin juga int dengan operasi dereference. Maksud saya adalah Anda juga harus memindai setiap pointer tunggal untuk menemukan orang-orang yang mereferensikan memori yang sama dengan yang baru saja Anda hapus, dan membatalkannya juga. Akan sangat intensif secara komputasi untuk memindai semua petunjuk untuk alamat itu dan membatalkannya, karena bahasa tersebut tidak dirancang untuk itu. (Meskipun beberapa bahasa lain menyusun referensi mereka untuk mencapai tujuan yang sama dengan cara yang berbeda.)

AaronLS
sumber
19

Pointer dapat disimpan di lebih dari satu variabel, menetapkan salah satunya ke NULL akan tetap meninggalkan pointer tidak valid di variabel lain. Jadi Anda tidak benar-benar mendapatkan banyak, Anda lebih cenderung menciptakan rasa aman yang salah.

Selain itu, Anda dapat membuat fungsi Anda sendiri yang melakukan apa yang Anda inginkan:

template<typename T>
void deleten(T *&ptr) {
  delete ptr;
  ptr = NULL;
}
sth
sumber
12

Karena sebenarnya tidak ada kebutuhan untuk itu, dan karena itu akan memerlukan penghapusan mengambil pointer-to-pointer daripada hanya pointer.

snemarch
sumber
benar, tetapi itu akan menghasilkan overhead yang sama
snemarch
7

deletesebagian besar digunakan dalam destruktor, dalam hal pengaturan anggota untuk NULL tidak ada gunanya. Beberapa baris kemudian, pada penutupan }, anggota tidak lagi ada. Di operator penugasan, penghapusan biasanya diikuti oleh penugasan.

Juga, itu akan membuat kode berikut ilegal:

T* const foo = new T;
delete foo;
MSalters
sumber
6

Inilah alasan lain; misalkan delete tidak menyetel argumennya ke NULL:

int *foo = new int;
int *bar = foo;
delete foo;

Haruskah bar diatur ke NULL? Bisakah Anda menggeneralisasi ini?

SingleNegationElimination
sumber
5

Jika Anda memiliki larik pointer, dan tindakan kedua Anda adalah menghapus larik kosong, maka tidak ada titik yang mengatur setiap nilai menjadi nol saat memori akan dibebaskan. Jika Anda ingin menjadi nol .. tulis nol untuk itu :)

Akun mati
sumber
4

C ++ memungkinkan Anda untuk mendefinisikan operator Anda sendiri dan menghapus baru sehingga misalnya mereka akan menggunakan pengalokasi kumpulan Anda sendiri. Jika Anda melakukan ini maka dimungkinkan untuk menggunakan yang baru dan menghapus dengan hal-hal yang tidak sepenuhnya alamat tetapi mengatakan indeks dalam kumpulan kolam Anda. Dalam konteks ini nilai NULL (0) mungkin memiliki makna hukum (merujuk pada item pertama dalam kumpulan).
Jadi setelah menghapus set NULL secara otomatis ke argumennya tidak selalu memiliki arti - set nilai ke nilai yang tidak valid. Nilai yang tidak valid mungkin tidak selalu NULL.

shoosh
sumber
4

Filsafat C ++ adalah "bayar hanya jika Anda menggunakannya". Saya pikir itu dapat menjawab pertanyaan Anda.

Juga kadang-kadang Anda bisa memiliki tumpukan Anda sendiri yang akan memulihkan memori yang dihapus .. atau kadang-kadang pointer tidak dimiliki oleh variabel apa pun. Atau pointer disimpan dalam beberapa variabel - mungkin nol hanya satu dari mereka.
Seperti yang Anda lihat ada banyak masalah dan kemungkinan masalah.

bayda
sumber
3

Mengatur pointer ke NULL secara otomatis tidak akan menyelesaikan sebagian besar masalah dengan penggunaan pointer buruk. Satu-satunya crash yang akan dihindari adalah jika Anda mencoba untuk menghapusnya dua kali. Bagaimana jika Anda memanggil fungsi anggota pada penunjuk seperti itu? Itu masih crash (dengan asumsi bahwa itu mengakses variabel anggota). C ++ tidak membatasi Anda untuk memanggil fungsi apa pun pada pointer NULL, juga tidak boleh melakukannya dari sudut pandang kinerja.


sumber
-1

Saya melihat orang memberikan jawaban aneh untuk pertanyaan ini.

ptr = NULL; Bagaimana pernyataan sederhana semacam itu dapat menyebabkan keterlambatan kinerja?

Jawaban lain mengatakan bahwa kita dapat memiliki banyak pointer yang menunjuk ke lokasi memori yang sama. Tentunya kita bisa. Dalam hal ini operasi hapus pada satu pointer hanya akan membuat pointer NULL (jika delete membuat pointer NULL) dan pointer lainnya akan menjadi non-NULL dan menunjuk ke lokasi memori yang bebas.

Solusi untuk ini seharusnya pengguna menghapus semua pointer yang menunjuk ke lokasi yang sama. Secara internal itu harus memeriksa apakah memori sudah dibebaskan daripada tidak bebas. Hanya buat pointer NULL.

Stroustrup dapat mendesain delete agar berfungsi dengan cara ini. Dia pikir programmer akan mengurus ini. Jadi dia mengabaikannya.

Nimesh Bapodra
sumber