سیپلاسپلاس یک قاعده دارد که بقیهاش از آن میآید: وقتی نام یک شی از دامنه بیرون میرود، مخربش خودکار اجرا میشود. لازم نیست چیزی صدا بزنید و در مسیر خطا هم اتفاق میافتد.
پیامد عملیاش این است: هر چیزی که باید آزاد شود، بسته شود یا رها شود، در یک مخرب بگذارید و به آن چیز یک دامنه بدهید. فایل، اتصال، قفل، و حافظه همه یک الگو دارند و هیچکدام به بلوک آزادسازی دستی نیاز ندارند.
ترتیب هم تصادفی نیست: مخربها به ترتیب وارونه ساخته شدن اجرا میشوند. یعنی اگر اول یک اتصال ساخته باشید و بعد یک تراکنش رویش، تراکنش اول بسته میشود و بعد اتصال، که همان ترتیبی است که میخواستید.
سه نوع اشارهگر، و پرسشی که میانشان انتخاب میکند
پرسش این است که چه کسی صاحب این شی است و چه کسی آزادش میکند.
std::unique_ptrیک صاحب دارد، کپی نمیشود و فقط منتقل میشودstd::shared_ptrچند صاحب دارد و با شمارش ارجاع آزاد میکند- اشارهگر خام یعنی «قرض گرفتهام و صاحبش نیستم»
پیشفرض باید اولی باشد و نه دومی. شمارش ارجاع هزینه دارد و مهمتر اینکه حلقه ارجاع میسازد: دو شی که به هم اشاره کنند هیچوقت آزاد نمیشوند، و راهحلش اشارهگر ضعیف است. همان مسئله در زبانهای با جمعکننده زباله هم هست: مقدارها کجا مینشینند و چه وقت آزاد میشوند.
کپی گران است و بیصدا
در سیپلاسپلاس انتساب یعنی کپی، و برای یک ظرف بزرگ یعنی کپی کل محتوا. هیچ خطایی نمیدهد و فقط کند میشود. پاس دادن به تابع هم همینطور است مگر آنکه ارجاع بگیرید، و برای همین قاعده رایج این است که پارامترهای بزرگ را با ارجاع ثابت بگیرید.
وقتی واقعا میخواهید مالکیت منتقل شود و نه کپی، حرکت دادن شکل درست است: محتوای شی مبدا به مقصد منتقل میشود و مبدا در حالتی معتبر ولی خالی میماند. این تفاوت میان کپی و انتقال، بزرگترین چیزی است که سیپلاسپلاس امروزی را از نسخههای پیش از سال ۲۰۱۱ جدا میکند.
جایی که کار گیر میکند، آموزش سیپلاسپلاس قدیمی است
در درسهای دانشگاهی فارسی، سیپلاسپلاس معمولا یعنی سی بهعلاوه کلاس، با new و delete دستی و آرایه خام. کسی که اینطور یاد گرفته، کدی مینویسد که همان خطاهای حافظه سی را دارد و فکر میکند زبان امنتری استفاده کرده. تفاوت واقعی از جایی شروع میشود که delete را ننویسید: با اشارهگر یکتا و ظرفهای استاندارد، بیشتر نشتیها و آزادسازیهای مضاعف اصلا ممکن نیستند. اگر در کدتان delete میبینید، تقریبا همیشه یعنی یک مخرب جا مانده.
ابزار، و سالی که این حرف درست است
در سال ۲۰۲۶، استاندارد جاافتاده برای پروژه تازه C++20 است و C++23 هم در کامپایلرهای اصلی پشتیبانی خوبی دارد؛ چیزی که از C++20 بیشترین تفاوت را میسازد ماژولها و مفهومها هستند. ابزار ساخت پیشفرض CMake است و متنباز و رایگان. برای پیدا کردن همان خطاهایی که این صفحه دربارهشان است، ضدعفونیکننده آدرس با یک پرچم روشن میشود و همراه خود کامپایلر میآید، و clang-tidy بخشی از آنها را پیش از اجرا میگوید.
پرسش بعدی این است که آن حافظهای که مخرب آزادش میکند از کجا آمده و آدرسها چطور کار میکنند، که آدرس، تخصیص، و خطاهایی که میسازند است. و زبانی که همین مالکیت را در زمان کامپایل بررسی میکند بهجای اینکه به قاعده تیمی بسپاردش، ایمنی حافظه، بدون جمعکننده زباله است.