new
ve delete
işleçleri
C++ ve işleçlerini kullanarak nesnelerin dinamik ayırmasını ve delete
serbest bırakılıp ayrılmasını new
destekler. Bu işleçler, boş depo (yığın olarak da bilinir) adlı bir havuzdan nesneler için bellek ayırır. new
işleci özel işlevinioperator new
, işleci ise delete
özel işlevini operator delete
çağırır.
C Çalışma Zamanı Kitaplığı ve C++ Standart Kitaplığı'ndaki kitaplık dosyalarının listesi için bkz . CRT Kitaplığı Özellikleri.
İşleç new
Derleyici, bunun gibi bir deyimini işlevine operator new
yönelik bir çağrıya çevirir:
char *pch = new char[BUFFER_SIZE];
İstek sıfır bayt depolama içinse, operator new
ayrı bir nesneye yönelik bir işaretçi döndürür. Başka bir ifadeyle, farklı işaretçiler döndürmek için operator new
tekrarlanan çağrılar.
Ayırma isteği için yetersiz bellek varsa, operator new
bir std::bad_alloc
özel durum oluşturur. Alternatif olarak, yerleştirme formunu new(std::nothrow)
kullandıysanız veya oluşturmayan operator new
destekte bağlantı sağladıysanız döndürürnullptr
. Daha fazla bilgi için bkz . Ayırma hatası davranışı.
İşlevler için operator new
iki kapsam aşağıdaki tabloda açıklanmıştır.
İşlevlerin operator new
kapsamı
İşleç | Scope |
---|---|
::operator new |
Global |
sınıf adı::operator new |
Sınıf |
öğesinin operator new
ilk bağımsız değişkeni türünde size_t
olmalıdır ve dönüş türü her zaman void*
olur.
İşleç yerleşik türlerdeki nesneleri, kullanıcı tanımlı operator new
işlevler içermeyen sınıf türü nesnelerini ve herhangi bir türde dizileri ayırmak için kullanıldığında genel operator new
işlev çağrılırnew
. işleci, bir öğesinin new
tanımlandığı operator new
bir sınıf türündeki nesneleri ayırmak için kullanıldığında, bu sınıfın operator new
çağrılır.
Bir operator new
sınıf için tanımlanan işlev, bu sınıf türündeki nesneler için genel operator new
işlevi gizleyen bir statik üye işlevidir (sanal olamaz). Belleği ayırmak ve belirli bir değere ayarlamak için kullanılan durumu new
göz önünde bulundurun:
#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;
}
için parantez new
içinde sağlanan bağımsız değişken bağımsız değişken olarak chInit
geçirilirBlanks::operator new
. Ancak genel operator new
işlev gizlenir ve aşağıdaki gibi bir kodun hata oluşturmasına neden olur:
Blanks *SomeBlanks = new Blanks;
Derleyici, sınıf bildiriminde üye dizisini new
ve delete
işleçleri destekler. Örnek:
class MyClass
{
public:
void * operator new[] (size_t)
{
return 0;
}
void operator delete[] (void*)
{
}
};
int main()
{
MyClass *pMyClass = new MyClass[5];
delete [] pMyClass;
}
Ayırma hatası davranışı
new
C++ Standart Kitaplığı'ndaki işlev, C++98'den bu yana C++ standardında belirtilen davranışı destekler. Ayırma isteği için bellek yetersiz olduğunda bir operator new
std::bad_alloc
özel durum oluşturur.
Eski C++ kodu başarısız ayırma için null işaretçi döndürdü. oluşturmayan sürümünü new
bekleyen kodunuz varsa programınızı ile nothrownew.obj
bağlayın. Dosya, nothrownew.obj
genel operator new
değerini ayırma başarısız olursa döndüren nullptr
bir sürümle değiştirir. operator new
artık atmıyor std::bad_alloc
. Ve diğer bağlayıcı seçeneği dosyaları hakkında nothrownew.obj
daha fazla bilgi için bkz . Bağlantı seçenekleri.
Aynı uygulamadaki null işaretçileri denetleen kodla genelden operator new
özel durumları denetleen kodu karıştıramazsınız. Ancak, yine de farklı davranan sınıf-yerel operator new
oluşturabilirsiniz. Bu olasılık, derleyicinin varsayılan olarak savunmada hareket etmesi ve çağrılarda new
null işaretçi dönüşleri için denetimler içermesi gerektiği anlamına gelir. Bu derleyici denetimlerini iyileştirmenin bir yolu hakkında daha fazla bilgi için bkz /Zc:throwingnew
. .
Yetersiz belleği işleme
Bir ifadeden new
başarısız ayırma için test yönteminiz, standart özel durum mekanizmasını mı yoksa bir dönüş mü kullandığınıza nullptr
bağlıdır. Standart C++ ayırıcının veya std::bad_alloc
öğesinden türetilmiş bir sınıf oluşturmasını std::bad_alloc
bekler. Bu örnekte gösterildiği gibi böyle bir özel durumu işleyebilirsiniz:
#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;
}
}
biçimini new
kullandığınızdanothrow
, bu örnekte gösterildiği gibi bir ayırma hatası için test edebilirsiniz:
#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;
}
}
Burada gösterildiği gibi geneli operator new
değiştirmek için dosya kullandığınızda nothrownew.obj
başarısız bellek ayırmayı test edebilirsiniz:
#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;
}
}
Başarısız bellek ayırma istekleri için bir işleyici sağlayabilirsiniz. Böyle bir hatayı işlemek için özel bir kurtarma yordamı yazmak mümkündür. Örneğin, ayrılmış bellek serbest bırakılabilir ve ayırmanın yeniden çalıştırılmasına izin verebilir. Daha fazla bilgi için bkz. _set_new_handler
.
İşleç delete
işleci kullanılarak new
dinamik olarak ayrılan bellek, işleci kullanılarak delete
serbestleştirilebilir. Delete işleci, kullanılabilir havuza geri bellek boşaltan işlevini çağırır operator delete
. işlecinin delete
kullanılması sınıf yıkıcısının (varsa) çağrılmasına da neden olur.
Genel ve sınıf kapsamlı operator delete
işlevler vardır. operator delete
Belirli bir sınıf için yalnızca bir işlev tanımlanabilir; tanımlanırsa genel operator delete
işlevi gizler. Genel operator delete
işlev her zaman herhangi bir türde diziler için çağrılır.
Genel operator delete
işlev. Genel operator delete
ve sınıf üyesi operator delete
işlevleri için iki form vardır:
void operator delete( void * );
void operator delete( void *, size_t );
Belirli bir sınıf için önceki iki biçimden yalnızca biri mevcut olabilir. İlk form, serbest bırakılan nesnenin işaretçisini içeren türünde void *
tek bir bağımsız değişken alır. İkinci form olan boyutlu serbest bırakma iki bağımsız değişken alır: birincisi serbest bırakmak için bellek bloğunun işaretçisidir ve ikincisi serbest bırakılanın bayt sayısıdır. Her iki formun da dönüş türü ( void
operator delete
değer döndüremez).
İkinci formun amacı, silinecek nesnenin doğru boyut kategorisini aramayı hızlandırmaktır. Bu bilgiler genellikle ayırmanın kendisine yakın bir noktada depolanmaz ve büyük olasılıkla çıkarılmamıştır. İkinci form, türetilmiş bir sınıfın nesnesini silmek için temel sınıftan bir işlev kullanıldığında kullanışlıdır operator delete
.
operator delete
İşlev statik olduğundan sanal olamaz. İşlev, operator delete
Üye Erişim Denetimi'nde açıklandığı gibi erişim denetimine uyar.
Aşağıdaki örnekte, bellek ayırmalarını ve operator delete
serbest bırakmalarını günlüğe kaydetmek için tasarlanmış kullanıcı tanımlı operator new
ve işlevler gösterilmektedir:
#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;
}
Yukarıdaki kod, "bellek sızıntısını" yani boş depoda ayrılan ancak hiçbir zaman serbest bırakılmayan belleği algılamak için kullanılabilir. Sızıntıları algılamak için, genel new
ve delete
işleçler belleği ayırma ve ayırmayı saymak için yeniden tanımlanır.
Derleyici, sınıf bildiriminde üye dizisini new
ve delete
işleçleri destekler. Örnek:
// 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;
}
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin