مدیریت حافظه در ++C با استفاده از new و delete

Managing Memory in C++ Using New and Delete

memory managment in c++

در این آموزش، ما به طور کارآمد مدیریت حافظه را در ++C با استفاده از عملیات‌های new و delete با کمک مثال‌ها، یاد خواهیم گرفت.

++C به ما این اجازه را می‌دهد که حافظه را به یک متغیر یا یک آرایه در زمان اجرا (run-time) اختصاص دهیم. این را به عنوان اختصاص دادن حافظه به طور پویا (‌dynamic) می‌‌شناسیم.

در دیگر زبان‌های برنامه‌نویسی مانند جاوا و پایتون، کامپایلر حافظه‌های اختصاص داده شده به متغیر‌ها را به طور خودکار مدیریت می‌کند. اما این موضوع در ++C صِدق نمی‌کند. در ++C ما باید به طور دستی حافظه‌ی اختصاص داده شده به صورت پویا را بعد این‌که استفاده‌ای از متغیر نداشتیم  آزاد یا به اصطلاح deallocate کنیم. ما می‌توانیم با استفاده از عملگرهای new و delete به ترتیب به طور پویا حافظه را اختصاص و آزاد کنیم.

عملگر new در ++C

عملگر new حافظه را به یک متغیر اختصاص می‌دهد، به این مثال توجه کنید:

// declare an int pointer
int* pointVar;

// dynamically allocate memory
// using the new keyword 
pointVar = new int;

// assign value to allocated memory
*pointVar = 45;

در اینجا، ما به طور پویا حافظه‌ را برای یک متغیر از نوع int با استفاده از عملگر new اختصاص دادیم. توجه داشته باشید که از اشاره‌گر pointVar برای اختصاص حافظه به صورت پویا استفاده شده است. این به این خاطر است که عملگر new آدرس مکان حافظه را بر‌می‌گرداند.

درمورد یک آرایه، عملگر new آدرس اولین عنصر از آرایه را برمی‌گرداند. در مثالا بالا، متوجه می‌شویم که نحوه (syntax) استفاده از عملگر new به این صورت است:

pointerVariable = new dataType;

عملگر delete

زمانی‌که ما دیگر نیاز به استفاده از متغیری که به صورت پویا آن را اعلام کردیم نداریم، می‌توانیم حافظه‌ای را که توسط متغیر گرفته شده است، آزاد کنیم. برای انجام این کار، عملگر delete استفاده شده است. این عملگر حافظه را به سیستم عامل برمی‌گرداند. این را هم با عنوان آزاد‌سازی حافظه یا memory deallocation می‌شناسیم.

نحوه‌ی یا syntax آن ( عملگر delete ) به این صورت است:

delete pointerVariable;

به قطعه کد زیر توجه کنید:

// declare an int pointer
int* pointVar;

// dynamically allocate memory
// for an int variable 
pointVar = new int;

// assign value to the variable memory
*pointVar = 45;

// print the value stored in memory
cout << *pointVar; // Output: 45

// deallocate the memory
delete pointVar

در اینجا ما حافظه را برای یک متغیر از نوع int با استفاده از اشاره‌گر pointVar به طور پویا اختصاص داده‌ایم. بعد از چاپ کردن محتوای pointVar، ما حافظه را با استفاده از delete آزاد کردیم.

نکته: اگر برنامه با استفاده از new از حافظه‌ی بلااستفاده‌ی زیادی استفاده کند، سیستم ممکن است هَنگ (‌crash) کند. چرا که هیچ حافظه‌ی برای سیستم‌عامل باقی نمی‌ماند. در این مورد، عملگر delete به سیستم کمک می‌کند تا از crash جلوگیری کند.

مثال 1: اختصاص دادن حافظه پویا در ++C

#include <iostream>
using namespace std;

int main() {
    // declare an int pointer
    int* pointInt;

    // declare a float pointer
    float* pointFloat;

    // dynamically allocate memory
    pointInt = new int;
    pointFloat = new float;

    // assigning value to the memory
    *pointInt = 45;
    *pointFloat = 45.45f;

    cout << *pointInt << endl;
    cout << *pointFloat << endl;

    // deallocate the memory
    delete pointInt;
    delete pointFloat;

    return 0;
}

خروجی قطعه‌ کُد بالا:

45
45.45

در این برنامه، حافظه را به 2 متغیر از نوع int و float به طور پویا اختصاص داد‌ه‌ایم. بعد از اختصاص دادن مقادیر به آن‌ها و چاپ آن‌ها، با استفاده از کد زیر حافظه‌های اختصاص داده شده به آن‌ها را آزاد می‌کنیم:

delete pointInt;
delete pointFloat;

نکته: اختصاص دادن حافظه به صورت پویا می‌تواند مدیریت حافظه را کارآمد‌تر کند. به خصوص برای آرایه‌ها، جایی که خیلی از وقت‌ها اندازه‌ی آرایه را تا زمان اجرا نمی‌دانیم.

مثال 2: عملگر‌های new و delete در ++C‌ برای آرایه‌ها

// C++ Program to store GPA of n number of students and display it
// where n is the number of students entered by the user

#include <iostream>
using namespace std;

int main() {
    int num;
    cout << "Enter total number of students: ";
    cin >> num;
    float* ptr;
    
    // memory allocation of num number of floats
    ptr = new float[num];

    cout << "Enter GPA of students." << endl;
    for (int i = 0; i < num; ++i) {
        cout << "Student" << i + 1 << ": ";
        cin >> *(ptr + i);
    }

    cout << "\nDisplaying GPA of students." << endl;
    for (int i = 0; i < num; ++i) {
        cout << "Student" << i + 1 << " :" << *(ptr + i) << endl;
    }

    // ptr memory is released
    delete[] ptr;

    return 0;
}

خروجی قطعه‌ کُد بالا:

Enter total number of students: 4
Enter GPA of students.
Student1: 3.6
Student2: 3.1
Student3: 3.9
Student4: 2.9

Displaying GPA of students.
Student1 :3.6
Student2 :3.1
Student3 :3.9
Student4 :2.9

در این برنامه، از کاربر خواسته شده تا تعداد دانش‌آموزان را وارد کرده و آن را در متغیر num ذخیره کند. سپس، حافظه‌ی ما به طور پویا با استفاده از new برای آرایه‌ از نوع float اختصاص داده‌شده است.

ما داده‌‌ها را به داخل آرایه وارد می‌کنیم (و بعدا آن‌ها چاپ می‌کنیم) با استفاده از علامت اشاره‌گر. بعد از این‌که دیگر نیازی به آرایه نداشتیم، حافظه‌ی آرایه را با استفاده از کد ;delete[] ptr آزاد می‌کنیم. توجه کنید که از [] بعد از delete استفاده کنید. ما از براکت‌ها [] برای نشان دادن این‌که حافظه‌ای که آزاد‌سازی می‌شود، یک آرایه است.

مثال 3؛ عملگر‌های new و delete در ++C برای اشیاء

#include <iostream>
using namespace std;

class Student {
    int age;

   public:

    // constructor initializes age to 12
    Student() : age(12) {}

    void getAge() {
        cout << "Age = " << age << endl;
    }
};

int main() {

    // dynamically declare Student object
    Student* ptr = new Student();

    // call getAge() function
    ptr->getAge();

    // ptr memory is released
    delete ptr;

    return 0;
}

خروجی کد بالا:

Age = 12

در این برنامه، یک کلاس Student ایجاده شده است که یک متغیر خصوصی (‌private) با نام  age دارد. متغیر age در سازنده‌ی پیش‌فرض ()Student با مقدار 12 مقداردهی اولیه شده است و مقدارش با تابع ()getAge چاپ می‌شود. در تابع ()main یک شیء Student با استفاده از عملگر new ایجاده شده و از اشاره‌گر ptr برای اشاره به آدرسش استفاده می‌کند.

هنگامی که شی ایجاد می‌شود، سازنده‌ ()Student متغیر age را با مقدار 12 مقداردهی اولیه می‌کند.

سپس تابع ()getAge را با استفاده از کد زیر، فراخوانی می‌کنیم:

ptr->getAge();

به عملگر فلش <- توجه کنید. این عملگر برای دسترسی به اعضای کلاس با استفاده از اشاره‌گرها استفاده می‌شود.


منبع: وب سایت programiz

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.