[C / C ++] C / C ++ - Speicherverwaltung, die Sie nicht verpassen dürfen!

1. C / C ++ - Speicherverteilung

  • Schauen Sie sich zuerst einen Code an:
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
    
    
 static int staticVar = 1;
 int localVar = 1;
 
 int num1[10] = {
    
    1, 2, 3, 4};
 char char2[] = "abcd";
 char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof (int)*4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
 free (ptr1);
 free (ptr3);
}

Entsprechender Speicherort:
Fügen Sie hier eine Bildbeschreibung ein

  • Stapel: Speichern Sie Funktionsparameter, lokale Variablen und Registerinformationen (Funktion endet, Stapelrahmen wird freigegeben), und der Stapel wächst nach unten
    • Die Standardgröße des Stack-Speicherplatzes unter Linux: 8192 KB = 8 MB
    • Windows-Stapelspeicher: 1024 KB = 1 MB
  • Heap: Dynamische Speicheranwendung, Malloc, Calloc, Realloc, muss kostenlos freigegeben werden, der Heap wächst nach oben
  • Datensegment: globale Variablen, durch statische Änderungen geänderte Daten (der Lebenszyklus stimmt mit dem Programm überein, das Programm beendet die Daten wird gelöscht)
  • Code-Snippet: Code- und schreibgeschützte Konstanten

Warum die Erinnerung in verschiedene Bereiche aufteilen?
Der Datentyp ist unterschiedlich, die Datenverwaltungsmethode ist ebenfalls unterschiedlich, um die Suche zur Aufteilung verschiedener Bereiche zu erleichtern

Zweitens Speicherverwaltung

2.1 C-Sprachspeicherverwaltung:

malloc 、 calloc 、 realloc

int* p1 = (int*)malloc(sizeof(int));		// 动态申请int空间大小,随机值
int* p2 = (int*)calloc(4, sizeof(int));		// 动态申请int空间大小,并赋值4
int* p3 = (int*)realloc(p2, sizeof(int) * 10);	//调整p2的空间大小为10个int大小

Gleicher Punkt:

  1. Der Rückgabewert ist ungültig *, muss beim Empfang zur Übertragung gezwungen werden
  2. Die Anwendung gibt NULL nicht zurück, daher muss sie vor der Verwendung leer sein

Unterschied:

  1. malloc (Größe): Bewerben Sie sich einfach für den Speicher der Größe Größe
  2. calloc (num, size): Die Größe des Anwendungsbereichs ist size, und der Wert wird den Daten zugewiesen
  3. Realloc (void * p, size): Passen Sie die Größe des Raums, auf den p zeigt, an die Größe an (vergrößern oder verkleinern). Wenn p NULL ist, ähnelt die Funktion malloc. Wenn die Größe des Leerzeichens hinter p kleiner als die Größe ist, suchen Sie ein neues Leerzeichen, das ausreichend groß ist, kopieren Sie den Inhalt des alten Leerzeichens und geben Sie schließlich die Größe des alten Leerzeichens frei.

Hinweis: Der von malloc angeforderte Speicherplatz ist etwas größer als erwartet. Im Objektmodell gibt es 32 Byte Attributinformationen (einschließlich der Größe des angeforderten Speichers usw.) und eine 4-Byte-Endposition bei den Rücken zu verhindern, außerhalb der Grenzen.

2.2 C ++ - Speicherverwaltung:

Warum erstellt C ++ eine neue Speicherverwaltungsmethode?
C ++ ist eine objektorientierte Programmierung. Es verwendet malloc, calloc und realloc, um die Größe des Klassenraums dynamisch zu öffnen. Es ruft den Konstruktor nicht auf, kann also nicht als Objekt bezeichnet werden. Wenn free aufgerufen wird, wird der Destruktor aufgerufen Nicht aufgerufen werden, um die internen Ressourcen des Objekts zu bereinigen. Kann Speicherlecks verursachen

  1. Anfordern / Freigeben eines einzelnen Typbereichs: Neu / Löschen
  2. Kontinuierlichen Typraum anwenden / freigeben: neu [] / löschen []

Dynamische Anwendung für integrierte Typen:

int* p1=new int(10);10初始化
int* p2=new int[10]{
    
    1,2,3,4,5,6,7,8,9,0}; 申请连续空间并初始化
delete p1;
delete[] p2;

Dynamische Anwendung für benutzerdefinierte Typen:

class Test
{
    
    
public:
    Test(int p = 0)
        :p_(p)
    {
    
    
        cout << "构造:" << this << endl;
    }
    ~Test()
    {
    
    
        cout << "析构:" << this << endl;
    }
private:
    int p_;
};

int main()
{
    
    
    Test* p1 = new Test(100);				//会调用构造函数(类内成员t被初始化成1),因此生成的为对象
    Test* p2 = (Test*)malloc(sizeof(Test));	//不会调用(类内成员t没有初始化),因此只能称为和类类型大小相同的堆空间
    delete p1;								//会调用析构函数,清理
    free(p2);								//只会释放开辟的空间
    return 0;
}

Der Unterschied zwischen Malloc und New:

  1. new ist ein Schlüsselwort in C ++, malloc ist eine Bibliotheksfunktion, daher muss die Header-Datei vor der Verwendung eingeführt werden
  2. malloc application / release of space ruft den Konstruktor / Destruktor nicht auf, new ruft den Konstruktor / Destruktor auf
  3. Die malloc-Anwendung schlägt fehl und gibt NULL zurück. Aufgrund der internen Implementierung von new wird kein Nullzeiger zurückgegeben.
  4. Der Rückgabewert von malloc ist void *, und new gibt einen Zeiger des entsprechenden Typs zurück, sodass keine Übertragung erzwungen werden muss, um empfangen zu werden

Hinweis:
new / delete, new [] / delete [], malloc \ free müssen übereinstimmen, da dies sonst zu einem Programmabsturz oder einem Speicherverlust führen kann

class Test
{
    
    
public:
    Test(int val = 0)
        :p_(new int(val))
    {
    
    
        cout << "构造:" << this << endl;
    }
    ~Test()
    {
    
    
        delete p_;
        cout << "析构:" << this << endl;
    }
private:
    int* p_;
};

int main()
{
    
    
    Test* p1 = (Test*)malloc(sizeof(Test));
    Test* p2 = new Test;
    Test* p3 = new Test[2];
    
    delete p1;      // 程序崩溃,malloc没有调用构造函数
    delete[] p1;    // 程序崩溃,malloc没有调用构造函数

    free(p2);       // 内存泄漏,free没有调用析构函数

    free(p3);       // 程序崩溃,连续空间只释放了一部分
    delete p3;      // 程序崩溃,连续空间只释放了一部分
    return 0;
}

Drei, Workflow neu / löschen

3.1 neu

  • 1. Beantragen Sie Heap-Speicherplatz
    • Rufen Sie die Funktion new * size des Operators void * auf, um Speicherplatz zu beantragen. Size ist die Speicherplatzgröße der Klasse, und rufen Sie malloc intern auf, um Speicherplatz zu beantragen
      • Erfolg: Kehren Sie zur ersten Adresse des Bereichs zurück
      • Fehler: Rufen Sie die Funktion _callnewh (Größe) auf, rufen Sie die vom Benutzer bereitgestellte Lösung auf. Wenn dies fehlschlägt, lösen Sie eine Ausnahme vom Typ bad_alloc aus und beantragen Sie weiterhin Speicherplatz
  • 2. Rufen Sie den Konstruktor auf, um den angeforderten Speicherplatz zu initialisieren

Zusammenfassung: Aufgrund der Art und Weise, wie die Funktion new () des Operators ausgeführt wird, gibt new nicht null zurück

3.2 löschen

  • 1. Rufen Sie den Destruktor auf, um die Ressourcen im Objekt zu bereinigen
  • 2. Rufen Sie die Funktion delete () des Operators auf und rufen Sie intern frei auf, um Speicherplatz freizugeben

3.3 neu []

  • 1. Um Leerzeichen zu beantragen, rufen Sie den Operator void * new [] (Größe) auf und rufen Sie intern die Funktion operator new () auf, um N Klassenräume anzuwenden
  • 2. Rufen Sie den Konstruktor N-mal auf, um N Objekte zu initialisieren

3.4 löschen []

  • 1. Rufen Sie den Destruktor N-mal auf, um die Speicherplatzressourcen zu bereinigen, auf die p zeigt
  • 2. Rufen Sie void operator delete [] (void * p) auf, um das Leerzeichen freizugeben, auf das p zeigt -> die Funktion zum Löschen des Operators wird intern aufgerufen

Viertens konvertieren Sie den von malloc geöffneten Klassenraum in Objekte

  • Der von malloc angeforderte Speicherplatz kann nicht als Objekt bezeichnet werden, da der Konstruktor nicht aufgerufen wird
  • Positionieren Sie den neuen Ausdruck: Rufen Sie den Konstruktor im geöffneten Heap-Bereich auf, initialisieren Sie den Klassenraum und machen Sie ihn zu einem Objekt
#include<iostream>
using namespace std;
class Test
{
    
    
public:
	Test(int t = 0)
		:_t(t), _p(new int)
	{
    
    
		cout << "Test(int):" << endl;
	}
	~Test()
	{
    
    
		delete _p;
		cout << "~Test():" << this << endl;
	}
private:
	int _t;
	int* _p;
};
int main()
{
    
    
	Test* pt = (Test*)malloc(sizeof(Test));
	new(pt) Test(100);		// 定位new表达式
	pt->~Test();			// 调用析构函数清理资源
	free(pt);				// 调用free释放空间
	return 0;
}

Ich denke du magst

Origin blog.csdn.net/qq_45691748/article/details/110225950
Empfohlen
Rangfolge