operator new
dan delete
C++ mendukung alokasi dinamis dan alokasi objek menggunakan new
operator dan delete
. Operator ini mengalokasikan memori untuk objek dari kumpulan yang disebut toko gratis (juga dikenal sebagai tumpukan). Operator new
memanggil fungsi operator new
khusus , dan delete
operator memanggil fungsi operator delete
khusus .
Untuk daftar file pustaka di Pustaka Runtime C dan Pustaka Standar C++, lihat Fitur Pustaka CRT.
Operator new
Pengkompilasi menerjemahkan pernyataan seperti ini ke dalam panggilan ke fungsi operator new
:
char *pch = new char[BUFFER_SIZE];
Jika permintaan adalah untuk nol byte penyimpanan, operator new
mengembalikan pointer ke objek yang berbeda. Artinya, panggilan berulang untuk operator new
mengembalikan pointer yang berbeda.
Jika tidak ada cukup memori untuk permintaan alokasi, operator new
berikan std::bad_alloc
pengecualian. Atau, ini mengembalikan nullptr
jika Anda telah menggunakan formulir new(std::nothrow)
penempatan , atau jika Anda telah menautkan dalam dukungan non-throwingoperator new
. Untuk informasi selengkapnya, lihat Perilaku kegagalan alokasi.
Dua cakupan untuk operator new
fungsi dijelaskan dalam tabel berikut.
Cakupan untuk operator new
fungsi
Operator | Scope |
---|---|
::operator new |
Global |
nama kelas::operator new |
Kelas |
Argumen pertama harus operator new
berjenis size_t
, dan jenis pengembalian selalu void*
.
Fungsi global operator new
dipanggil ketika new
operator digunakan untuk mengalokasikan objek jenis bawaan, objek jenis kelas yang tidak berisi fungsi yang ditentukan operator new
pengguna, dan array dari jenis apa pun. new
Ketika operator digunakan untuk mengalokasikan objek dari jenis kelas tempat operator new
didefinisikan, kelas tersebut operator new
dipanggil.
operator new
Fungsi yang ditentukan untuk kelas adalah fungsi anggota statis (yang tidak dapat menjadi virtual) yang menyembunyikan fungsi global operator new
untuk objek dari jenis kelas tersebut. Pertimbangkan kasus di mana new
digunakan untuk mengalokasikan dan mengatur memori ke nilai tertentu:
#include <malloc.h>
#include <memory.h>
class Blanks
{
public:
Blanks(){}
void *operator new( size_t stAllocateBlock, char chInit );
};
void *Blanks::operator new( size_t stAllocateBlock, char chInit )
{
void *pvTemp = malloc( stAllocateBlock );
if( pvTemp != 0 )
memset( pvTemp, chInit, stAllocateBlock );
return pvTemp;
}
// For discrete objects of type Blanks, the global operator new function
// is hidden. Therefore, the following code allocates an object of type
// Blanks and initializes it to 0xa5
int main()
{
Blanks *a5 = new(0xa5) Blanks;
return a5 != 0;
}
Argumen yang disediakan dalam tanda kurung ke new
diteruskan ke Blanks::operator new
sebagai chInit
argumen. Namun, fungsi global operator new
disembunyikan, menyebabkan kode seperti berikut menghasilkan kesalahan:
Blanks *SomeBlanks = new Blanks;
Kompilator mendukung array new
anggota dan delete
operator dalam deklarasi kelas. Contohnya:
class MyClass
{
public:
void * operator new[] (size_t)
{
return 0;
}
void operator delete[] (void*)
{
}
};
int main()
{
MyClass *pMyClass = new MyClass[5];
delete [] pMyClass;
}
Perilaku kegagalan alokasi
Fungsi new
dalam Pustaka Standar C++ mendukung perilaku yang ditentukan dalam standar C++ sejak C++98. Ketika tidak ada cukup memori untuk permintaan alokasi, operator new
melemparkan std::bad_alloc
pengecualian.
Kode C++ yang lebih lama mengembalikan pointer null untuk alokasi yang gagal. Jika Anda memiliki kode yang mengharapkan versi non-throwing , new
tautkan program Anda dengan nothrownew.obj
. File nothrownew.obj
menggantikan global operator new
dengan versi yang mengembalikan nullptr
jika alokasi gagal. operator new
tidak lagi melempar .std::bad_alloc
Untuk informasi selengkapnya tentang nothrownew.obj
dan file opsi linker lainnya, lihat Opsi tautan.
Anda tidak dapat mencampur kode yang memeriksa pengecualian dari global operator new
dengan kode yang memeriksa pointer null dalam aplikasi yang sama. Namun, Anda masih dapat membuat kelas lokal operator new
yang berulah secara berbeda. Kemungkinan ini berarti pengkompilasi harus bertindak defensif secara default dan menyertakan pemeriksaan untuk pengembalian pointer null dalam new
panggilan. Untuk informasi selengkapnya tentang cara mengoptimalkan pemeriksaan kompilator ini, lihat /Zc:throwingnew
.
Menangani memori yang tidak mencukup
Cara Anda menguji alokasi yang gagal dari new
ekspresi bergantung pada apakah Anda menggunakan mekanisme pengecualian standar, atau Anda menggunakan pengembalian nullptr
. Standard C++ mengharapkan alokator untuk melemparkan salah satu std::bad_alloc
atau kelas yang berasal dari std::bad_alloc
. Anda dapat menangani pengecualian seperti yang ditunjukkan dalam sampel ini:
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
try {
int *pI = new int[BIG_NUMBER];
}
catch (bad_alloc& ex) {
cout << "Caught bad_alloc: " << ex.what() << endl;
return -1;
}
}
Saat Anda menggunakan nothrow
bentuk new
, Anda dapat menguji kegagalan alokasi seperti yang ditunjukkan dalam sampel ini:
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new(nothrow) int[BIG_NUMBER];
if ( pI == nullptr ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
Anda dapat menguji alokasi memori yang gagal saat Anda telah menggunakan nothrownew.obj
file untuk menggantikan global operator new
seperti yang ditunjukkan di sini:
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new int[BIG_NUMBER];
if ( !pI ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
Anda dapat menyediakan handler untuk permintaan alokasi memori yang gagal. Dimungkinkan untuk menulis rutinitas pemulihan kustom untuk menangani kegagalan tersebut. Ini bisa, misalnya, merilis beberapa memori yang dipesan, lalu memungkinkan alokasi berjalan lagi. Untuk informasi selengkapnya, lihat _set_new_handler
.
Operator delete
Memori yang dialokasikan secara dinamis menggunakan new
operator dapat dibebaskan menggunakan delete
operator. Operator penghapusan memanggil operator delete
fungsi , yang membebaskan memori kembali ke kumpulan yang tersedia. delete
Menggunakan operator juga menyebabkan destruktor kelas (jika ada) dipanggil.
Ada fungsi global dan cakupan operator delete
kelas. Hanya satu operator delete
fungsi yang dapat didefinisikan untuk kelas tertentu; jika ditentukan, fungsi global operator delete
akan disembunyikan. Fungsi global operator delete
selalu dipanggil untuk array dari semua jenis.
Fungsi global operator delete
. Ada dua formulir untuk fungsi global operator delete
dan anggota operator delete
kelas:
void operator delete( void * );
void operator delete( void *, size_t );
Hanya salah satu dari dua bentuk sebelumnya yang dapat hadir untuk kelas tertentu. Formulir pertama mengambil satu argumen jenis void *
, yang berisi penunjuk ke objek untuk dibatalkan alokasinya. Formulir kedua, alokasi berukuran besar, mengambil dua argumen: yang pertama adalah pointer ke blok memori untuk dibatalkan alokasinya, dan yang kedua adalah jumlah byte yang akan dibatalkan alokasinya. Jenis pengembalian kedua formulir adalah void
(operator delete
tidak dapat mengembalikan nilai).
Niat formulir kedua adalah untuk mempercepat pencarian kategori ukuran objek yang benar untuk dihapus. Informasi ini sering tidak disimpan di dekat alokasi itu sendiri, dan kemungkinan tidak di-cache. Formulir kedua berguna ketika operator delete
fungsi dari kelas dasar digunakan untuk menghapus objek kelas turunan.
Fungsinya operator delete
statis, sehingga tidak bisa virtual. Fungsi ini operator delete
mematuhi kontrol akses, seperti yang dijelaskan dalam Kontrol Akses Anggota.
Contoh berikut menunjukkan fungsi dan operator delete
yang ditentukan operator new
pengguna yang dirancang untuk mencatat alokasi dan alokasi memori:
#include <iostream>
using namespace std;
int fLogMemory = 0; // Perform logging (0=no; nonzero=yes)?
int cBlocksAllocated = 0; // Count of blocks allocated.
// User-defined operator new.
void *operator new( size_t stAllocateBlock ) {
static int fInOpNew = 0; // Guard flag.
if ( fLogMemory && !fInOpNew ) {
fInOpNew = 1;
clog << "Memory block " << ++cBlocksAllocated
<< " allocated for " << stAllocateBlock
<< " bytes\n";
fInOpNew = 0;
}
return malloc( stAllocateBlock );
}
// User-defined operator delete.
void operator delete( void *pvMem ) {
static int fInOpDelete = 0; // Guard flag.
if ( fLogMemory && !fInOpDelete ) {
fInOpDelete = 1;
clog << "Memory block " << cBlocksAllocated--
<< " deallocated\n";
fInOpDelete = 0;
}
free( pvMem );
}
int main( int argc, char *argv[] ) {
fLogMemory = 1; // Turn logging on
if( argc > 1 )
for( int i = 0; i < atoi( argv[1] ); ++i ) {
char *pMem = new char[10];
delete[] pMem;
}
fLogMemory = 0; // Turn logging off.
return cBlocksAllocated;
}
Kode sebelumnya dapat digunakan untuk mendeteksi "kebocoran memori", yaitu memori yang dialokasikan di toko gratis tetapi tidak pernah dibebaskan. Untuk mendeteksi kebocoran, global new
dan delete
operator didefinisikan ulang untuk menghitung alokasi dan alokasi memori.
Kompilator mendukung array new
anggota dan delete
operator dalam deklarasi kelas. Contohnya:
// spec1_the_operator_delete_function2.cpp
// compile with: /c
class X {
public:
void * operator new[] (size_t) {
return 0;
}
void operator delete[] (void*) {}
};
void f() {
X *pX = new X[5];
delete [] pX;
}
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk