خوراک پی سی کدنویس

ورود کاربران

آمار سایت

اعضا : 135
محتوا : 67
پیوندها : 6
بازدیدهای محتوا : 58458

حاضرین در سایت

 38 مهمان حاضر

برای نمایش بهتر سایت، از مرورگر استاندارد فایرفاکس استفاده کنید! مرورگر اینترنت اکسپلورر متعلق به دهه گذشته است!

firefox icon

Valid XHTML 1.0 Transitional Valid CSS!

تخصیص و آزاد سازی حافظه با استفاده از عملگرهای new و delete

1 امتیاز

محدودیتهای آرایه

در مبحث اشاره گرها ذکر کردیم که یکی از ویژگیهای مهم اشاره گرها امکان تخصیص و آزادسازی حافظه است. برای اینکه بخشی از حافظه را در اختیار بگیریم، یک راه استفاده از آرایه است که قبلا توضیح داده شد. لیکن آرایه دو محدودیت بزرگ دارد: اول اینکه طول ثابتی داشته و از این رو به طور پویا (دینامیک) و در زمان اجرای برنامه نمی توان طول آن را تعیین کرد یا تغییر داد. دوم اینکه چون حافظه مورد نیاز آرایه از فضای پشته (Stack) تخصیص می یابد، و هر برنامه ای فضای پشته ی محدودی دارد (که تا سقف معینی قابل افزایش است) از این رو نمی توان آرایه های خیلی بزرگ (با حجم مثلا 20 مگابایت) تعریف کرد و اگر چنین کاری بکنیم، لینکر خطا خواهد داد:

//Assigning large memory using arrays, makes exception
 char LargeData[20*1024*1024];

نحوه تخصیص حافظه با استفاده از اشاره گر

با استفاده از عملگر new می توانیم حافظه ای به یک اشاره گر تخصیص دهیم. با توجه به اینکه این حافظه از فضای heap تخصیص داده می شود و هیپ یک فضای بزرگی از حافظه است، نسبت به آرایه، محدودیت به مراتب کمتری داریم. برای اینکه بیشتر با هیپ و پشته آشنا شویم ابتدا تفاوت این دو را بیان می کنیم. قبل از آن باید ذکر کنم که چیزی به نام هیپ و پشته در استاندارد C++ تعریف نشده، لیکن این چیزی است که جا افتاده و همه برنامه نویسان می شناسند!

تفاوت هیپ و پشته

پشته برای ذخیره سازی موقت متغیرها استفاده می شود و حافظه تخصیص داده شده به متغیرها به محض اینکه از محدوده ی دید برنامه یا تابع خارج شوند، به طور خودکار آزاد می شود. با توجه به حجم محدود پشته، هر گونه تلاشی برای تخصیص حافظه ی زیاد از پشته منجر به Stack Overflow شده و اجرای برنامه با خطای سهمگینی متوقف خواهد شد! این موضوع زمانی که تعداد متغیرهای زیادی در برنامه استفاده شود یا تابعی به صورت تو در تو توابع دیگر را صدا بزند (مثل توابع بازگشتی) اتفاق می افتد.

هیپ حافظه ی آزادیست که تخصیص آن توسط برنامه نویس صورت می پذیرد و به طور خودکار آزاد نمی شود (مراقب نشت حافظه باشید!).

هیپ فضای بسیار بزرگی از حافظه ی RAM است و از این رو برای تخصیص آرایه ها، ساختارها و کلاسهای بزرگ مناسب تر است.

نحوه استفاده از عملگر new

در کد زیر با استفاده از عملگر new به میزان 50 خانه حافظه از نوع int به اشاره گر data تخصیص می دهیم:
int* data = new int[50];

دقت کنید که اگر به جای کروشه از پرانتز استفاده کنید new int (50) کامپایلر خطا نمی گیرد! چون دستور درستی است، لیکن فقط یک خانه حافظه تخصیص داده و آن را با مقدار 50 پر می کند! این یکی از اشتباهات مرسوم در برنامه نویسی C++ است که خودم در سالهای آغازین یادگیری C++ بارها چوبش را خورده ام.

وقتی حافظه ای تخصیص داده شد، دسترسی به المانهای حافظه مانند دسترسی به المانهای آرایه است. البته روش دیگری هم وجود دارد. مثلا اگر بخواهیم عنصر اول و یازدهم این حافظه را با مقادیر 1360 و 1388 پر کنیم، به یکی از دو صورت زیر عمل می کنیم:

data[0]=1360; // first element will be changed to 1360
data[10] = 1388; // 11th element will be changed to 1388
 
*data=1360; // first element will be changed to 1360
*(data+10)=1388; // 11th element will be changed to 1388

آزاد کردن حافظه با استفاده از دستور delete

حافظه ای که از هیپ اختصاص داده می شود، مادامیکه برنامه نویس آن را پاک نکند، حذف نخواهد شد. لذا باید بسیار دقت کرد که هر حافظه ای که تخصیص می دهیم، در موقعیت مناسب (پس از اینکه کار ما با آن تمام شد) آن را آزاد کنیم. برای آزاد سازی حافظه در C++ از دستور delete استفاده می کنیم:
delete [] data;

علامت [] لازم نیست، هر چند زمانی که بیش از یک خانه حافظه را تخصیص می دهیم، بهتر است که از این علامت استفاده کنیم.

نکته مهم: استفاده مجدد از دستور delete برای حذف کردن حافظه ای که قبلا حذف شده است، عواقب وخیمی به دنبال دارد که ساده ترین آن پیغام مشهور don't send جناب میکروسافت است! برای رهایی از این موضوع بهتر است که اشاره گرها را حتما در زمان مقداردهی اولیه و پس از حذف با مقدار NULL پر کنیم (اشاره گری که به هیچ جایی اشاره نمی کند) و هنگامی که قصد آزادسازی آن را داریم تنها در صورتی آن را آزاد کنیم که مقدار آن مخالف NULL باشد. این یک تکنیک کاملا شناخته شده است و تمام برنامه نویسان حرفه ای آن را انجام می دهند:

 
int* data = NULL; // Always initialize pointers to NULL or use new operator to assign some memory
data = new int[50];
// Make use of data
...
// Now we don't need it more, and want to free its memory
if(data != NULL) // or simply if(data)
   delete [] data;
...
//Now if we try to delete it again, nothing will occur
if(data)//will not execute, since data is NULL
   delete [] data;
 
  • pari
    اگه واستون مقدوره یه برنامه خوب که نحوه ارسال اشارهگر به تابع رو نشون بده واسم میل کنید خیلی ممنون میشم :0
اظهار نظر
مشخصات شما:
نظر:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):s:!::?::idea::arrow:
امنیت
کد آنتی اسپم نمایش داده شده در عکس را وارد کنید.