שיעורי מודול (2/2)
std::weak_ptr
למרות ש-std::shared_ptr שימושי ביותר, הסתמכות על בעלות משותפת בלבד יכולה להוביל לבעיה המכונה הפניה מעגלית (או תלות מחזורית).
אם שני אובייקטים או יותר כל אחד מכיל shared_ptr המצביע על השני, נוצרת לולאה סגורה. במצב זה, ספירת ההתייחסות של אף אחד מהאובייקטים לא תגיע לעולם לאפס, מה שמונע ביטול הקצאה וגורם לדליפת זיכרון.
מה זה std::weak_ptr
כדי לשבור מחזורי בעלות, הספרייה הסטנדרטית מציעה std::weak_ptr. זהו מצביע חכם שמתבונן באובייקט המנוהל על ידי shared_ptr, אך בלי להגדיל את ספירת הפניות.
היא אינה הבעלים של המשאב ישירות, ולכן היא אינה מונעת את השמדתו.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Does not increment reference count!אימות וגישה למשאב
מכיוון ש-weak_ptr אינו הבעלים של המשאב, ניתן לבטל את הקצאת המשאב בכל עת (כאשר כל המופעים המשויכים shared_ptr יוצאים מהתחום).
כדי להשתמש במשאב הנצפה, עלינו:
- בדוק אם הוא עדיין בתוקף באמצעות
expired(). - המר באופן זמני את
weak_ptrל-shared_ptrבאמצעות שיטתlock(). אם המשאב עדיין פעיל,lock()מחזירshared_ptrחוקי, אחרת הוא מחזיר מצביע null (nullptr).
if (!weak.expired()) {
// lock() creates a temporary shared_ptr to ensure safe access
if (std::shared_ptr<int> sharedAccess = weak.lock()) {
std::cout << *sharedAccess << std::endl;
}
} else {
std::cout << "Resource deallocated!" << std::endl;
}נסה זאת בעצמך
הכריז על std::weak_ptr<int> בשם wPtr אותחל מ-sPtr. לאחר מכן הדפס את התוצאה הבוליאנית שהוחזרה על ידי wPtr.expired() באמצעות std::cout.
הצג רמז
הכריז על ה-'weak_ptr' המציין את אותו סוג גנרי '<int>' והקצה לו 'sPtr' ישירות.
הפתרון זמין לאחר 3 ניסיונות
השתמש בשיטת lock() ב-wPtr כדי להשיג shared_ptr זמני. אם הפעולה מצליחה (המצביע אינו ריק), הדפס את הערך שחסר.
הצג רמז
אתחול משתנה בתוך בלוק `if` על ידי קריאה `wPtr.lock()`, ולאחר מכן הדפס את המשאב המפנה אותו עם הכוכבית `*`.
הפתרון זמין לאחר 3 ניסיונות