تخطَّ إلى المحتوى

std::optional

تمثيل غياب القيمة std::optional

std::optional<T> من C++17 يحمل إمّا قيمة من النوع T أو لا شيء، بشكل صريح وآمن — بديل عن مؤشّرات nullptr أو قيم سنتينل (-1) لتمثيل "لا توجد نتيجة".

قبل C++17، تمثيل نتيجة قد لا توجد (بحث فاشل مثلًا) كان يعتمد على حلول معيبة: مؤشّر nullptr (يحتاج تخصيص ذاكرة إضافي)، قيمة سنتينل مثل -1 (تتعارض مع قيم حقيقية محتملة)، أو استثناء (مكلف لحالة متوقّعة وليست خطأ فعلي). optional<T> يحل هذا بحاوية صغيرة تحمل T مباشرة (بلا تخصيص ذاكرة على الكومة) أو تكون فارغة، مع تحقّق واضح عبر has_value أو operator bool.

الصياغة

std::optional<Type> name = value; // أو std::nullopt للحالة الفارغة
if (name.has_value()) { ... }
Type v = name.value_or(defaultValue);

📄 مثال

#include <optional>

std::optional<int> findAge(const std::map<std::string, int>& ages,
                            const std::string& n) {
    auto it = ages.find(n);
    if (it != ages.end()) return it->second;
    return std::nullopt;
}

if (auto age = findAge(ages, "سارة")) {
    std::cout << *age;
}
int safe = findAge(ages, "غير موجود").value_or(0);

أهم النقاط

العنصرالوظيفة
has_value() / operator boolفحص هل يحتوي قيمة قبل الوصول إليها
value()يرجع القيمة أو يرمي std::bad_optional_access لو فارغ
value_or(default)آمن دائمًا — يرجع القيمة أو البديل المحدَّد دون رمي استثناء
operator*وصول مباشر بلا فحص — سلوك غير معرَّف لو استُخدم على optional فارغ

💡 نصائح عملية

  • استخدمه كنوع إرجاع لأي دالة قد تفشل بإيجاد نتيجة بدل مؤشّر أو قيمة سنتينل غامضة
  • value_or أأمن دائمًا من value() أو * عندما لا تريد التعامل مع استثناء أو فحص صريح بكل مرة

⚠️ أخطاء شائعة

  • استدعاء value() أو * على optional فارغ دون فحص مسبق — استثناء أو سلوك غير معرَّف
  • استخدام optional<T*> بدل optional<T> ظنًا أنه ضروري — optional يعمل مباشرة مع القيم دون حاجة لمؤشّر إضافي

خصائص ذات صلة

🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار CPP الكامل بالعربي.