Std की घोषणा कैसे करें :: unique_ptr और इसका क्या उपयोग है?


95

मैं यह समझने की कोशिश std::unique_ptrकरता हूं कि कैसे काम करता है और उसके लिए मुझे यह दस्तावेज मिला । लेखक निम्नलिखित उदाहरण से शुरू होता है:

#include <utility>  //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();

जो मुझे भ्रमित कर रहा है, वह है इस पंक्ति में

unique_ptr<int> uptr (new int(3));

हम पूर्णांक को एक तर्क के रूप में उपयोग करते हैं (गोल कोष्ठक के बीच) और यहाँ

unique_ptr<double> uptr2 (pd);

हमने एक संकेतक का उपयोग एक तर्क के रूप में किया। इससे क्या फ़र्क पड़ता है?

मेरे लिए भी जो स्पष्ट नहीं है, वह यह है कि पॉइंटर्स, इस तरह से घोषित किए गए "सामान्य" तरीके से घोषित किए गए पॉइंटर्स से अलग होंगे।


13
new int(3)नए के लिए एक पॉइंटर लौटाता है int, ठीक उसी तरह जैसे pdनया करने के लिए एक पॉइंटर था double
डेविड श्वार्ट्ज

जवाबों:


89

unique_ptr<T>कच्चे पॉइंटर का निर्माणकर्ता किसी प्रकार की वस्तु को Tस्वीकार करता है (इसलिए, यह स्वीकार करता है T*)।

पहले उदाहरण में:

unique_ptr<int> uptr (new int(3));

सूचक एक newअभिव्यक्ति का परिणाम है , जबकि दूसरे उदाहरण में:

unique_ptr<double> uptr2 (pd);

सूचक pdचर में संग्रहीत किया जाता है।

वैचारिक रूप से, कुछ भी नहीं बदलता है (आप unique_ptrएक कच्चे सूचक से निर्माण कर रहे हैं ), लेकिन दूसरा दृष्टिकोण संभवतः अधिक खतरनाक है, क्योंकि यह आपको, उदाहरण के लिए, करने की अनुमति देगा:

unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);

इस प्रकार दो अद्वितीय बिंदु होते हैं जो प्रभावी रूप से एक ही वस्तु को कूटबद्ध करते हैं (इस प्रकार एक अद्वितीय सूचक के शब्दार्थ का उल्लंघन करते हैं )।

यही कारण है कि एक अद्वितीय सूचक बनाने के लिए पहला रूप बेहतर है, जब संभव हो। ध्यान दें, कि C ++ 14 में हम कर पाएंगे:

unique_ptr<int> p = make_unique<int>(42);

जो स्पष्ट और सुरक्षित दोनों है। अब आपकी इस शंका के विषय में:

मेरे लिए भी जो स्पष्ट नहीं है, वह यह है कि पॉइंटर्स, इस तरह से घोषित किए गए "सामान्य" तरीके से घोषित किए गए पॉइंटर्स से अलग होंगे।

स्मार्ट पॉइंटर्स को ऑब्जेक्ट के स्वामित्व के मॉडल के लिए माना जाता है, और स्वचालित रूप से इंगित ऑब्जेक्ट को नष्ट करने का ख्याल रखता है जब उस ऑब्जेक्ट का अंतिम (स्मार्ट, मालिक) सूचक कार्यक्षेत्र से बाहर हो जाता है।

इस तरह आपको deleteगतिशील रूप से आबंटित वस्तुओं पर करने के लिए याद रखने की ज़रूरत नहीं है - स्मार्ट पॉइंटर का विनाशकर्ता आपके लिए ऐसा करेगा - और न ही इस बारे में चिंता करने के लिए कि क्या आप पहले से नष्ट हो चुकी किसी वस्तु के लिए एक (झूलने वाला) सूचक को निष्क्रिय नहीं करेंगे:

{
    unique_ptr<int> p = make_unique<int>(42);
    // Going out of scope...
}
// I did not leak my integer here! The destructor of unique_ptr called delete

अब unique_ptrएक स्मार्ट पॉइंटर है जो अद्वितीय स्वामित्व वाला मॉडल है, जिसका अर्थ है कि आपके कार्यक्रम में किसी भी समय इंगित ऑब्जेक्ट के लिए केवल एक (मालिक) सूचक होगा - यही कारण unique_ptrहै कि गैर-प्रतिलिपि योग्य है।

जब तक आप एक तरह से स्मार्ट पॉइंटर्स का उपयोग करते हैं, जो आपके द्वारा अनुपालन करने के लिए आवश्यक निहित अनुबंध को नहीं तोड़ते हैं, आपके पास यह गारंटी होगी कि कोई मेमोरी लीक नहीं होगी, और आपकी वस्तु के लिए उचित स्वामित्व नीति लागू की जाएगी। रॉ पॉइंटर्स आपको इसकी गारंटी नहीं देते हैं।


3
नमस्ते, मैं कोड या model object ownership, के बारे में कुछ भी समझ नहीं सका । क्या आप इन अवधारणाओं को सीखने के लिए विषय / संसाधन सुझा सकते हैं? integer leakenforcing ownership policy for object
udun

1
मैं unique_ptrएक त्रुटि प्राप्त किए बिना, उपयोग नहीं कर सकता : The text ">" is unexpected. It may be that this token was intended as a template argument list terminator but the name is not known to be a template.भले ही मेरे पास है #include <utility>और #include <memory>। कोई सुझाव?
अनाम

15

असाइनमेंट की दोनों अवधारणाओं में unique_ptr पर काम करने में कोई अंतर नहीं है।

int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);

के समान है

unique_ptr<int> uptr (new int(3));

यहाँ पर अनूठे_ptr स्वतः कब्जे वाले स्थान को हटा देता है uptr


इस तरह से घोषित किए गए पॉइंटर्स, "सामान्य" तरीके से घोषित किए गए पॉइंटर्स से अलग होंगे।

यदि आप हीप स्पेस ( नए कीवर्ड या मॉलोक का उपयोग करके ) में एक पूर्णांक बनाते हैं , तो आपको उस मेमोरी को अपने आप हटा देना होगा ( क्रमशः डिलीट या फ्री का उपयोग करके )।

नीचे दिए गए कोड में,

int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;

यहां, आपको heapInt को हटाना होगा, जब इसका उपयोग किया जाता है। यदि इसे हटाया नहीं जाता है, तो मेमोरी लीकेज होता है।

इस तरह की मेमोरी लीक से बचने के लिए unique_ptr का उपयोग किया जाता है, जहां unique_ptr स्वचालित रूप से heapInt द्वारा कब्जा किए गए स्थान को हटा देता है जब यह दायरे से बाहर हो जाता है। तो, आपको unique_ptr के लिए डिलीट या फ्री की जरूरत नहीं है ।


10

अद्वितीय पॉइंटर्स की गारंटी दी जाती है कि वे उस वस्तु को नष्ट कर दें जो वे दायरे से बाहर जाते हैं। http://en.cppreference.com/w/cpp/memory/unique_ptr

इस मामले में:

unique_ptr<double> uptr2 (pd);

pduptr2दायरे से बाहर जाने पर नष्ट हो जाएगा । यह स्वचालित रूप से हटाने के द्वारा स्मृति प्रबंधन की सुविधा देता है।

का मामला unique_ptr<int> uptr (new int(3));अलग नहीं है, सिवाय इसके कि कच्चा सूचक यहां किसी भी चर को नहीं सौंपा गया है।


-1

निर्माण से , निर्माणकर्ताओं में से एक std::unique_ptrहै

स्पष्ट यूनिक_प्रटर (पॉइंटर पी) नॉइसेप्ट;

तो एक नया बनाने के std::unique_ptrलिए अपने निर्माता को एक सूचक पारित करना है।

unique_ptr<int> uptr (new int(3));

या जैसा है वैसा ही है

int *int_ptr = new int(3);
std::unique_ptr<int> uptr (int_ptr);

अलग है कि आप इसे उपयोग करने के बाद साफ करने के लिए नहीं है। यदि आप std::unique_ptr(स्मार्ट पॉइंटर) का उपयोग नहीं करते हैं , तो आपको इसे इस तरह हटाना होगा

delete int_ptr;

जब आपको इसकी आवश्यकता नहीं होगी या यह मेमोरी रिसाव का कारण बनेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.