Auto_ptr को क्यों निकाला जा रहा है?


92

मैंने सुना auto_ptrहै C ++ 11 में पदावनत किया जा रहा है। इसका क्या कारण है?

इसके अलावा मैं auto_ptrऔर के बीच का अंतर जानना चाहूंगा shared_ptr


जवाबों:


91

के लिए प्रत्यक्ष प्रतिस्थापन auto_ptr(या किसी एक के लिए निकटतम चीज) है unique_ptr। जहाँ तक "समस्या" चला जाता है, यह बहुत आसान है: auto_ptrजब यह सौंपा जाता है तो स्वामित्व स्थानांतरित करता है। unique_ptrस्वामित्व भी स्थानांतरित करता है, लेकिन चाल शब्दार्थों के कोडीकरण और प्रतिद्वंद्विता संदर्भों के जादू के लिए धन्यवाद, यह स्वाभाविक रूप से बहुत अधिक कर सकता है। यह बाकी मानक पुस्तकालय के साथ "फिट" भी काफी बेहतर है (हालांकि, निष्पक्षता में, उनमें से कुछ को हमेशा की नकल की आवश्यकता के बजाय कदम शब्दार्थ को समायोजित करने के लिए बदलते पुस्तकालय के बाकी हिस्सों के लिए धन्यवाद है)।

नाम में परिवर्तन भी एक स्वागत योग्य है (IMO) - auto_ptrयह वास्तव में आपको इसके बारे में ज्यादा नहीं बताता है कि यह क्या करने की कोशिश करता है, जबकि unique_ptrजो प्रदान किया गया है उसका काफी उचित (यदि प्रतिकूल) विवरण है।


24
बस auto_ptrनाम पर एक नोट : ऑटो स्वचालित चर के रूप में स्वचालित रूप से सुझाव देता है, और यह एक चीज को संदर्भित करता auto_ptrहै: ऐसा करें: प्रबंधित संसाधन को उसके विध्वंसक (जब यह दायरे से बाहर हो जाता है) को नष्ट कर दें।
विन्केन्जो पीआई

13
अधिक जानकारी: यहाँ पदावनत करने के लिए आधिकारिक विवरण दिया गया है auto_ptr: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…
हावर्ड हिनान्ट

@ हॉर्डहिनंत दिलचस्प डॉक! यह एक अर्थ में अजीब है कि अगर std :: सॉर्ट () में std :: unique_ptr के लिए एक विशेषज्ञता है, तो आवश्यकतानुसार कदम शब्दार्थ का उपयोग करें। मुझे आश्चर्य है कि std :: सॉर्ट () dd में उल्लिखित कॉपी समस्या को सही करने के लिए std :: auto_ptr के लिए विशेष नहीं किया जा सकता है। अग्रिम में धन्यवाद।
हेई

2
@ हे: के std::sortलिए एक विशेषज्ञता नहीं है unique_ptr। इसके बजाय इसे कभी भी कॉपी न करने के लिए फिर से निर्दिष्ट किया गया था। तो auto_ptrवास्तव में आधुनिक के साथ काम करता हैsort । लेकिन C ++ 98/03 sortयहाँ केवल एक उदाहरण एल्गोरिथ्म है: कोई भी जेनेरिक अल्गोरिद्म (std-supply या user-लिखा) जो मानता है कि कॉपी सिंटैक्स में कॉपी सिमेंटिक्स है, संभवत: एक रन-टाइम एरर होगा जिसका उपयोग किया जाता है auto_ptr, क्योंकि auto_ptrचुपचाप चलता है कॉपी सिंटैक्स के साथ । मुद्दा अभी की तुलना में बहुत बड़ा है sort
हावर्ड हिनांट

35

मुझे मौजूदा उत्तर बहुत अच्छे लगे, लेकिन बिंदुओं के पीओवी से। IMO, एक आदर्श उत्तर में उपयोगकर्ता / प्रोग्रामर का परिप्रेक्ष्य उत्तर होना चाहिए।

पहली बात पहले (जैसा कि उनके जवाब में जेरी कॉफ़िन ने बताया)

  • स्थिति के आधार पर auto_ptr को shared_ptr या unique_ptr से बदला जा सकता है

share_ptr: यदि आप संसाधन / मेमोरी को मुक्त करने के बारे में चिंतित हैं और यदि आपके पास एक से अधिक फ़ंक्शन हैं जो ऑब्जेक्ट AT-DIFFERENT समय का उपयोग कर सकते हैं, तो साझा करें_ptr के साथ।

DIFFERENT-Times द्वारा, ऐसी स्थिति के बारे में सोचें जहां ऑब्जेक्ट-ptr को कई डेटा-स्ट्रक्चर में संग्रहीत किया जाता है और बाद में एक्सेस किया जाता है। कई धागे, निश्चित रूप से एक और उदाहरण है।

unique_ptr: यदि आप सभी चिंतित हैं तो मेमोरी को खाली कर रहा है, और ऑब्जेक्ट तक पहुंच अनुक्रमिक है, तो unique_ptr पर जाएं।

SEQUENTIAL द्वारा, मेरा मतलब है, किसी भी बिंदु पर वस्तु को एक संदर्भ से एक्सेस किया जाएगा। उदा। एक ऐसी वस्तु जो सृष्टिकर्ता द्वारा निर्माण के तुरंत बाद बनाई और इस्तेमाल की गई थी। निर्माण के बाद ऑब्जेक्ट को FIRST डेटा-स्ट्रक्चर में संग्रहीत किया जाता है । तब या तो ऑब्जेक्ट डेटा-संरचना के बाद नष्ट हो जाता है या सेकंड डेटा-स्ट्रक्चर में चला जाता है ।

इस लाइन से, मैं स्मार्ट-पॉइंटर्स के रूप में साझा / अद्वितीय _ptr का उल्लेख करूंगा। (auto_ptr स्मार्ट-पॉइंटर BUT भी है क्योंकि इसमें डिज़ाइन की खामियां हैं, जिसके लिए उन्हें पदावनत किया जा रहा है, और जो मुझे लगता है कि मैं अगली पंक्तियों में इंगित करूँगा, उन्हें स्मार्ट-पॉइंटर के साथ समूहीकृत नहीं किया जाना चाहिए।)

Auto -ptr को स्मार्ट-पॉइंटर के पक्ष में पदावनत करने के लिए एकल सबसे महत्वपूर्ण कारण असाइनमेंट-शब्दार्थ है यदि यह इस कारण से नहीं था, तो उन्होंने इसे पदावनत करने के बजाय auto_ptr में कदम अर्थ के सभी नए उपहार जोड़े होंगे। चूंकि असाइनमेंट-शब्दार्थ सबसे अधिक नापसंद करने वाला फीचर था, वे चाहते थे कि यह सुविधा चली जाए, लेकिन चूंकि कोड लिखा हुआ है जो उस शब्दार्थ का उपयोग करता है, (जो मानक-समिति बदल नहीं सकते हैं), उन्हें auto_rr के बजाय जाने देना था इसे संशोधित कर रहा है।

लिंक से: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/

Unqiue_ptr द्वारा समर्थित असाइनमेंट की तरह

  • चाल असाइनमेंट (1)
  • अशक्त सूचक असाइन करें (2)
  • टाइप-कास्ट असाइनमेंट (3)
  • कॉपी असाइनमेंट (हटाए गए!) (4)

से: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/

Auto_ptr द्वारा समर्थित असाइनमेंट की तरह

  • कॉपी असाइनमेंट (4) अपराधी

अब इस कारण से आकर कॉपी का असाइनमेंट अपने आप में कितना नापसंद था, मेरे पास यह सिद्धांत है:

  1. सभी प्रोग्रामर किताबें या मानक नहीं पढ़ते हैं
  2. इसके चेहरे पर auto_ptr, आपको ऑब्जेक्ट के स्वामित्व का वादा करता है
  3. थोड़ा- * (दंडित इरादा), ऑटो_प्र्टर का खंड, जिसे सभी प्रोग्रामर द्वारा नहीं पढ़ा जाता है, एक ऑटो_प्रटर को दूसरे को असाइन करने और स्वामित्व स्थानांतरित करने की अनुमति देता है।
  4. अनुसंधान ने दिखाया है कि यह व्यवहार सभी उपयोग के 3.1415926535% के लिए लक्षित है, और अन्य मामलों में अनपेक्षित है।

अनपेक्षित व्यवहार वास्तव में नापसंद है और इसलिए auto_ptr के लिए नापसंद है।

(प्रोग्रामर्स के 3.1415926536% के लिए, जो जानबूझकर स्वामित्व को स्थानांतरित करना चाहते हैं C ++ 11 ने उन्हें std :: move () दिया, जिसने कोड को पढ़ने और बनाए रखने वाले सभी इंटर्न के लिए अपना इरादा क्रिस्टल स्पष्ट कर दिया।)


1
चूंकि आप कभी भीauto_ptr एक ही वस्तु की ओर इशारा करते हुए दो मान नहीं चाहते हैं (चूंकि वे साझा स्वामित्व नहीं देते हैं, इसलिए मरने वाला पहला व्यक्ति दूसरे को एक घातक विरासत के साथ छोड़ देगा; यह unique_ptrउपयोग के लिए भी सही है ), क्या आप सुझाव दे सकते हैं कि क्या इरादा था ; शेष 96.8584073465% सभी उपयोग?
मार्क वैन लीउवेन

उन सभी के लिए नहीं बोल सकता, लेकिन मुझे लगता है, उन्हें लगता है कि वस्तु स्वामित्व को स्थानांतरित किया जा रहा है और न केवल दोहराया गया है, जो कि गलत है।
अजीत गंगा

@AjeetGanga निम्नलिखित वाक्यांश में 'छोटा- * (दण्डित उद्देश्य),' का उल्लेख '' दण्डित उद्देश्य '' के रूप में किया गया है। यह वाक्यांश मेरे लिए नया है और किसी भी तरह मैंने इसे गुज़ारा और यह पता चला कि कुछ मज़ाक है जो यहाँ उद्देश्यपूर्ण ढंग से किया गया था। वह मज़ाक यहाँ क्या है? बस यह जानने के लिए उत्सुक हैं।
विन्थो मोंटेटिक

@AjeetGanga आपने 'द लिटिल- * (सज़ा का उद्देश्य), ऑटो_प्ट्र का क्लॉज, जो सभी प्रोग्रामर द्वारा पढ़ा नहीं जाता है, की अनुमति देता है, एक auto_ptr को दूसरे में असाइन करने, और स्वामित्व को स्थानांतरित करता है'। मान लें कि मेरे पास पूर्णांक के रूप में दो ऑटो ptr और b हैं। मैं असाइनमेंट कर रहा हूं क्योंकि *a=*b;यहां केवल b की वैल्यू कॉपी की जाती है a। मुझे आशा है कि बी और बी दोनों का स्वामित्व अभी भी एक ही लोगों के पास है। आपने उल्लेख किया है कि ओवेरियनशिप को स्थानांतरित कर दिया जाएगा। ये कैसे होगा?
विन्थॉ मोंटेटिक

@VINOTHENERGETIC Ajeet किसी auto_ptrऑब्जेक्ट को स्वयं असाइन करने के बारे में बात कर रहा था । अपने इंगित किए गए मान से / पर असाइन करने का न तो स्वामित्व पर कोई प्रभाव पड़ता है, न ही प्रासंगिकता पर। मुझे आशा है कि आप अभी भी उपयोग नहीं कर रहे हैं auto_ptr?
अंडरस्कोर_ड

23

shared_ptrकंटेनर के अंदर संग्रहीत किया जा सकता है। auto_ptrनहीं कर सकता।

BTW unique_ptrवास्तव में प्रत्यक्ष auto_ptrप्रतिस्थापन है, यह दोनों की सर्वोत्तम विशेषताओं को जोड़ती है std::auto_ptrऔर boost::scoped_ptr


11

फिर भी एक और अंतर समझाने के लिए ले लो ...।

कार्यात्मक रूप से, C ++ 11 का std::unique_ptr"निश्चित" हैstd::auto_ptr : निष्पादन के दौरान किसी भी समय दोनों - उपयुक्त हैं - एक इंगित करने वाली वस्तु के लिए एक ही स्मार्ट-पॉइंटर मालिक होना चाहिए।

महत्वपूर्ण अंतर कॉपी-निर्माण या असाइनमेंट में एक और अन-एक्सपायरिंग स्मार्ट पॉइंटर से है, जो =>नीचे दी गई लाइनों पर दिखाया गया है :

   std::auto_ptr<T> ap(...);
   std::auto_ptr<T> ap2(get_ap_to_T());   // take expiring ownership
=> std::auto_ptr<T> ap3(ap);  // take un-expiring ownership ala ap3(ap.release());
   ap->xyz;  // oops... can still try to use ap, expecting it to be non-NULL

   std::unique_ptr<T> up(...);
   std::unique_ptr<T> up2(get_up_to_T());   // take expiring ownership
=> std::unique_ptr<T> up3(up);  // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up));  // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release());   // EXPLICIT code allowed

ऊपर, ap3चुपचाप "चोरी" के स्वामित्व *ap, apसेट करने के लिए जा रहा है nullptr, और समस्या यह है कि बहुत आसानी से हो सकता है, बिना प्रोग्रामर अपनी सुरक्षा के माध्यम से सोचा था।

उदाहरण के लिए, यदि class/ a structका कोई std::auto_ptrसदस्य है, तो एक उदाहरण की एक प्रति बना releaseरहा है, उदाहरण के लिए कॉपी की जा रही पॉइंटर से पॉइंटर होगा : यह अजीब और खतरनाक रूप से भ्रमित करने वाला शब्दार्थ है क्योंकि आमतौर पर किसी चीज को कॉपी करने से वह संशोधित नहीं होता है। क्लास / स्ट्रक्चर ऑथर के लिए यह आसान है कि जब वे इन्वर्टर और स्टेट के बारे में तर्क दे तो पॉइंटर की रिलीज़ को नजरअंदाज कर दें, और परिणामतः गलती से स्मार्ट-पॉइंटर को डीरेल करने का प्रयास करें, या अभी भी इंगित डेटा के एक्सेस / स्वामित्व की उम्मीद नहीं की है।


auto_ptr चुपचाप
कैमिनो

3

Auto_ptr का उपयोग STL कंटेनरों में नहीं किया जा सकता क्योंकि इसमें एक कॉपी कंस्ट्रक्टर है जो कंटेनर CopyConstructible की आवश्यकताओं को पूरा नहीं करता है । unique_ptr एक कॉपी कंस्ट्रक्टर को लागू नहीं करता है, इसलिए कंटेनर वैकल्पिक तरीकों का उपयोग करते हैं। unique_ptr को कंटेनरों में उपयोग किया जा सकता है और यह साझा एल्गोरिथम की तुलना में std एल्गोरिदम के लिए तेज़ है।

#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>

using namespace std;

int main() {
  cout << boolalpha;
  cout << "is_copy_constructible:" << endl;
  cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
  cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
  cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;

  vector<int> i_v;
  i_v.push_back(1);
  cout << "i_v=" << i_v[0] << endl;
  vector<int> i_v2=i_v;
  cout << "i_v2=" << i_v2[0] << endl;

  vector< unique_ptr<int> > u_v;
  u_v.push_back(unique_ptr<int>(new int(2)));
  cout << "u_v=" << *u_v[0] << endl;
  //vector< unique_ptr<int> > u_v2=u_v;  //will not compile, need is_copy_constructible == true
  vector< unique_ptr<int> > u_v2 =std::move(u_v);  // but can be moved
  cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;

  vector< shared_ptr<int> > s_v;
  shared_ptr<int> s(new int(3));
  s_v.push_back(s);
  cout << "s_v=" << *s_v[0] << endl;
  vector< shared_ptr<int> > s_v2=s_v;
  cout << "s_v2=" << *s_v2[0] << endl;

  vector< auto_ptr<int> > a_v;  //USAGE ERROR

  return 0;
}

>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
   vector< auto_ptr<int> > a_v;  //USAGE ERROR
           ^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.