shared_ptr
मूवमेंट शब्दकूट जरूरी नहीं है कि जब आप किसी मान को वापस कर रहे हों तो यह सब बड़ा हो जाए - और जब / यदि आप एक (या कुछ इसी तरह) का उपयोग करते हैं, तो आप शायद समय से पहले निराशा कर रहे हों। वास्तव में, लगभग सभी आधुनिक संकलक ऐसा करते हैं जिसे रिटर्न वैल्यू ऑप्टिमाइज़ेशन (आरवीओ) और नामांकित रिटर्न वैल्यू ऑप्टिमाइज़ेशन (एनआरवीओ) कहा जाता है। इसका अर्थ है कि एक मूल्य के लिए लौट रहे हैं, बजाय वास्तव में मूल्य को कॉपी कि सब पर, वे बस एक छिपे हुए पॉइंटर / संदर्भ को पास करते हैं, जहां रिटर्न के बाद मूल्य को सौंपा जा रहा है, और फ़ंक्शन का उपयोग उस मूल्य को बनाने के लिए होता है जहां यह समाप्त होने जा रहा है। C ++ मानक में इसे अनुमति देने के लिए विशेष प्रावधान शामिल हैं, इसलिए भले ही (उदाहरण के लिए) आपके कॉपी कंस्ट्रक्टर के साइड इफेक्ट्स दिखाई देते हों, मूल्य को वापस करने के लिए कॉपी कंस्ट्रक्टर का उपयोग करना आवश्यक नहीं है। उदाहरण के लिए:
#include <vector>
#include <numeric>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <iterator>
class X {
std::vector<int> a;
public:
X() {
std::generate_n(std::back_inserter(a), 32767, ::rand);
}
X(X const &x) {
a = x.a;
std::cout << "Copy ctor invoked\n";
}
int sum() { return std::accumulate(a.begin(), a.end(), 0); }
};
X func() {
return X();
}
int main() {
X x = func();
std::cout << "sum = " << x.sum();
return 0;
};
यहां मूल विचार काफी सरल है: पर्याप्त सामग्री के साथ एक वर्ग बनाएं जिसे हम इसे कॉपी करने से बचें, यदि संभव हो तो ( std::vector
हम 32767 यादृच्छिक ints के साथ भरें)। हमारे पास एक स्पष्ट प्रतिलिपि ctor है जो हमें दिखाएगा कि कब / अगर यह कॉपी किया जाता है। ऑब्जेक्ट में यादृच्छिक मानों के साथ कुछ करने के लिए हमारे पास थोड़ा अधिक कोड है, इसलिए ऑप्टिमाइज़र (कम से कम आसानी से) कक्षा के बारे में सब कुछ खत्म नहीं करेगा क्योंकि यह कुछ भी नहीं करता है।
फिर हमारे पास एक फ़ंक्शन से इन ऑब्जेक्ट्स में से एक को वापस करने के लिए कुछ कोड होते हैं, और फिर ऑब्जेक्ट को वास्तव में बनाया गया यह सुनिश्चित करने के लिए योग का उपयोग करते हैं, न कि पूरी तरह से अनदेखा। जब हम इसे चलाते हैं, तो कम से कम सबसे हाल के / आधुनिक संकलक के साथ, हम पाते हैं कि हमने जो कॉपी कंस्ट्रक्टर लिखा है, वह कभी भी नहीं चलता है - और हाँ, मुझे पूरा यकीन है कि एक के साथ एक फास्ट कॉपी shared_ptr
अभी भी कोई कॉपी करने की तुलना में धीमी है बिल्कुल भी।
मूविंग आपको उन चीजों की एक उचित संख्या करने की अनुमति देता है जो आप उनके बिना बस (सीधे) नहीं कर सकते थे। बाहरी मर्ज सॉर्ट के "मर्ज" भाग पर विचार करें - आपके पास, 8 फाइलें हैं, जिन्हें आप एक साथ मर्ज करने जा रहे हैं। आदर्श रूप से आप उन सभी फ़ाइलों को एक में रखना चाहते हैं vector
- लेकिन चूंकि vector
(C ++ 03 के रूप में) तत्वों को कॉपी करने में सक्षम होना चाहिए, और ifstream
कॉपी नहीं किया जा सकता है, आप कुछ के साथ अटक गए हैं , unique_ptr
/ shared_ptr
या उस आदेश पर कुछ उन्हें वेक्टर में डालने में सक्षम होने के लिए। ध्यान दें कि भले ही (उदाहरण के लिए) हम reserve
अंतरिक्ष में हैं, vector
इसलिए हमें यकीन है कि हमारे ifstream
एस को वास्तव में कभी भी कॉपी नहीं किया जाएगा, कंपाइलर को पता नहीं चलेगा, इसलिए कोड का संकलन नहीं होगा, जबकि हम जानते हैं कि कॉपी कंस्ट्रक्टर कभी नहीं होगा वैसे भी इस्तेमाल किया।
हालांकि यह अभी भी कॉपी नहीं किया जा सकता है, C ++ 11 में स्थानांतरित किया ifstream
जा सकता है। इस मामले में, वस्तुओं को शायद कभी स्थानांतरित नहीं किया जाएगा, लेकिन यह तथ्य कि वे हो सकते हैं यदि आवश्यक हो तो संकलक को खुश रखता है, इसलिए हम अपनी ifstream
वस्तुओं को vector
सीधे, बिना किसी स्मार्ट पॉइंटर हैक के रख सकते हैं ।
एक वेक्टर जो विस्तार करता है वह उस समय का एक बहुत ही अच्छा उदाहरण है जो शब्दार्थ को वास्तव में आगे बढ़ा सकता है / हालांकि उपयोगी है। इस मामले में, आरवीओ / एनआरवीओ मदद नहीं करेगा, क्योंकि हम एक फ़ंक्शन (या कुछ भी समान) से वापसी मूल्य के साथ काम नहीं कर रहे हैं। हमारे पास कुछ वस्तुओं को रखने वाला एक वेक्टर है, और हम उन वस्तुओं को स्मृति के नए, बड़े हिस्से में स्थानांतरित करना चाहते हैं।
C ++ 03 में, जो नई मेमोरी में ऑब्जेक्ट्स की कॉपी बनाकर किया गया था, फिर पुरानी मेमोरी में पुरानी वस्तुओं को नष्ट कर दिया। उन सभी प्रतियों को बनाना पुराने लोगों को दूर फेंकने के लिए, हालांकि, समय की काफी बर्बादी थी। C ++ 11 में, आप उनसे बदले जाने की अपेक्षा कर सकते हैं। यह आम तौर पर हमें देता है, संक्षेप में, एक (आमतौर पर बहुत धीमी) गहरी प्रति के बजाय एक उथले प्रति करते हैं। दूसरे शब्दों में, एक स्ट्रिंग या वेक्टर के साथ (केवल कुछ उदाहरणों के लिए) हम ऑब्जेक्ट में सूचक (ओं) को कॉपी करते हैं, इसके बजाय उन सभी डेटा की प्रतियां बनाते हैं जिन्हें इंगित करते हैं।
shared_ptr
तेजी से नकल के लिए सिर्फ एक खबरदार ) और अगर स्थानांतरित शब्दार्थ लगभग कोई कोडिंग-, शब्दार्थ- और स्वच्छता-दंड के साथ ही प्राप्त कर सकते हैं।