2012-01-18 7 views
10

मैं वर्तमान में "सी ++ प्रोग्रामिंग भाषा: विशेष संस्करण" पढ़ रहा हूँ में देरी की:सुझाई गति सुधार जब तुरंत मान के साथ स्ट्रिंग को परिभाषित करने के बजाय

लिए Bjarne Stroustrup द्वारा और पेज 133 पर यह निम्नलिखित में कहा गया है उपयोगकर्ता परिभाषित प्रकार, तक एक चर की परिभाषा को स्थगित करने के लिए एक उपयुक्त प्रारंभकर्ता उपलब्ध है, जिससे प्रदर्शन बेहतर हो सकता है। उदाहरण के लिए:

string s; /* .... */ s = "The best is the enemy of the good."; 

आसानी से

string s = "Voltaire"; 

बहुत धीमी हो सकता है मैं यह कहा गया आसानी से कर सकते हैं पता है, यह जरूरी तो नहीं होगा, लेकिन सिर्फ मान लीजिए जिसका अर्थ है ऐसा होता है

यह संभावित प्रदर्शन वृद्धि क्यों करेगा?

क्या यह केवल उपयोगकर्ता द्वारा परिभाषित प्रकारों (या यहां तक ​​कि एसटीएल प्रकार) के साथ है या यह int, float आदि के साथ भी मामला है?

+0

नीचे दिए गए उत्तरों के अलावा, यह सहायता की जा सकती है: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.22 – dsign

उत्तर

9

मैं कहूंगा कि यह मुख्य रूप से गैर-तुच्छ डिफ़ॉल्ट डिफॉल्ट कन्स्ट्रक्टर वाले प्रकारों के बारे में है, कम से कम जहां तक ​​प्रदर्शन का संबंध है।

दो दृष्टिकोणों के बीच अंतर यह है कि है:

  • पहले संस्करण में, एक खाली स्ट्रिंग पहले निर्माण किया है (डिफ़ॉल्ट निर्माता का उपयोग कर); तो असाइनमेंट ऑपरेटर का उपयोग डिफ़ॉल्ट कन्स्ट्रक्टर द्वारा किए गए काम को प्रभावी ढंग से फेंकने और स्ट्रिंग को नया मान असाइन करने के लिए किया जाता है।
  • दूसरे संस्करण में, आवश्यक मूल्य निर्माण के बिंदु पर तुरंत सेट किया गया है।

बेशक, यह प्राथमिकता बताने में वाकई मुश्किल है कि इससे प्रदर्शन में कितना बड़ा अंतर आएगा।

+0

प्रदर्शन अंतर उपयोगकर्ता परिभाषित प्रकारों के लिए उल्लेखनीय है। व्यावहारिक रूप से पीओडी प्रकारों के लिए कोई नहीं। –

7
  1. यह में समय लगता है एक डिफ़ॉल्ट निर्माता निष्पादित। बाद में में स्ट्रिंग को प्रारंभ करने के लिए ओवरराइड करना, असाइनमेंट ऑपरेटर भी समय लगता है।

  2. निष्पादन कभी भी असाइनमेंट तक नहीं पहुंच सकता है, जब फ़ंक्शन होता है (return कथन या अपवाद के कारण) डिफ़ॉल्ट कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर के आमंत्रण के बीच छोड़ दिया जाता है। उस स्थिति में, ऑब्जेक्ट डिफ़ॉल्ट-प्रारंभिक अनावश्यक रूप से था।

  3. क्रियान्वयन प्रदर्शन बर्बाद यकीन है कि वस्तु के नाशक कहा जाता है, तो एक अपवाद फेंक दिया जाता है बनाने के लिए हो सकता है। यदि ऑब्जेक्ट को बाद के दायरे में शुरू किया गया है जो कभी नहीं पहुंचा है, तो इसकी आवश्यकता नहीं है।

+1

मुझे लगता है कि दायरे का मुद्दा यहां सबसे महत्वपूर्ण बात है, और अन्य सभी उत्तरों ने इससे झुकाया है। स्ट्रॉस्ट्रप से स्पष्ट नहीं है कि बाद के मामले में, आप चर का उपयोग पूरी तरह से करने से बच सकते हैं। –

1

क्योंकि:

string s; /* .... */ s = "The best is the enemy of the good.";  

दो आपरेशन शामिल है: निर्माण और असाइनमेंट

जबकि:

string s = "Voltaire"; 

केवल निर्माण करना शामिल।

यह Member Initializer lists over Assignment in Constructor body चुनने के बराबर है।

string s;   // Default constructor 
string s = "..."; // Default constructor followed by operator assignment 
string s("..."); // Constructor with parameters passed in 

स्ट्रिंग वर्ग स्मृति को आबंटित करने की जरूरत है:

-1

वर्ग तीन तरीके स्ट्रिंग प्रारंभ करने में है। एक बार यह जानता है कि इसे कितनी मेमोरी चाहिए, इसे आवंटित करना बेहतर है।

+2

दूसरा मामला प्रारंभिकरण की प्रतिलिपि है, और कभी भी डिफ़ॉल्ट कन्स्ट्रक्टर या असाइनमेंट ऑपरेटर का उपयोग नहीं करता है। यह तकनीकी रूप से रूपांतरण सीटीओआर के माध्यम से अस्थायी निर्माण का निर्माण करता है और उसके बाद 'एस' के निर्माण की प्रतिलिपि बनाता है, लेकिन अनावश्यक प्रतिलिपि आमतौर पर elided है, इसे प्रत्यक्ष प्रारंभिक (केस 3) के बराबर बनाते हैं। –

0

यह एक अच्छा सवाल है। आप सही हैं, यह केवल जटिल प्रकारों के साथ होता है। अर्थात। कक्षाएं और structs, std :: स्ट्रिंग ऐसी वस्तु है। यहां शामिल वास्तविक मुद्दे को कन्स्ट्रक्टर के साथ करना है।

जब एक वस्तु बन जाता है, अर्थात

std::string s; 

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

आप पर बाद में कार्य करें:

s = "hello world!"; 

यह यह क्या किया है के सबसे फेंक और यह एक नया तार के साथ सामग्री है को बदलने के लिए तैयार हो जाओ करने के लिए वर्ग का कारण बनता है। यदि आप मान जब चर परिभाषित किया गया है सेट

यह वास्तव में एक भी आपरेशन करने के लिए कम हो जाता है, अर्थात्:

std::string s = "Hello world"; 

वास्तव में, यदि आप एक डिबगर में कोड को देखने के लिए, एक अलग निर्माता एक बार निष्पादित करेंगे ऑब्जेक्ट को बनाने के बजाय और फिर, अलग-अलग, मान सेट करना। वास्तव में, पिछले कोड बाहर काम करता है के रूप में ही:

std::string s("Hello world"); 

मुझे आशा है कि एक सा बातें स्पष्ट करने के लिए मदद की।

+1

असल में, एक अच्छा कार्यान्वयन के 'स्ट्रिंग' डिफ़ॉल्ट कन्स्ट्रक्टर शायद आवश्यक रूप से स्मृति आवंटित नहीं करता है। मुझे यकीन है कि जीसीसी का 'वेक्टर' नहीं है। –

+1

वास्तविक लागत शायद यह तथ्य है कि असाइनमेंट निर्माण से अधिक जटिल है, क्योंकि इसे स्ट्रिंग की पिछली स्थिति का निपटान और/या पुन: उपयोग करने पर विचार करना है। निर्माता जानता है कि कोई पिछली स्थिति नहीं है। –

0

विचार करें कि दोनों मामलों में क्या होता है।पहले मामले में:

  • डिफ़ॉल्ट निर्माता "एस"
  • असाइनमेंट ऑपरेटर "एस"

दूसरे मामले में के लिए बुलाया के लिए कहा जाता है, पहले विचार करना प्रतिलिपि इलिजन साथ कि इस string s("Voltaire") के बराबर है , इस प्रकार:

  • सी-स्ट्रिंग निर्माता कहा जाता

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

यह अतिरिक्त लागत केवल उपयोगकर्ता-प्रकारों पर लागू होनी चाहिए क्योंकि लागत डिफ़ॉल्ट कन्स्ट्रक्टर में है। Int जैसे किसी भी प्राचीन प्रकार के लिए, या वास्तव में किसी भी छोटे कन्स्ट्रक्टर/प्रतिलिपि के साथ, डिफ़ॉल्ट कन्स्ट्रक्टर के लिए कोई कीमत नहीं है - डेटा को प्रारंभ नहीं किया जाएगा (जब फ़ंक्शन स्कोप में)।

0

इससे संभावित प्रदर्शन में वृद्धि क्यों होगी?

पहले मामले में डिफ़ॉल्ट प्रारंभिकता शामिल है, इसके बाद असाइनमेंट; दूसरे में मूल्य से प्रारंभिकता शामिल है। डिफ़ॉल्ट प्रारंभिक कार्य कुछ कार्य कर सकता है जिसे बाद में असाइनमेंट द्वारा फिर से किया जाना चाहिए (या यहां तक ​​कि पूर्ववत) होना चाहिए, और इसलिए पहले मामले में दूसरे की तुलना में अधिक काम शामिल हो सकता है।

क्या यह केवल उपयोगकर्ता द्वारा परिभाषित प्रकारों (या यहां तक ​​कि एसटीएल प्रकार) के साथ है या यह int, float, आदि के साथ भी मामला है?

यह केवल उपयोगकर्ता द्वारा परिभाषित प्रकारों के साथ ही है; और फिर यह इस बात पर निर्भर करता है कि रचनाकार और असाइनमेंट ऑपरेटर वास्तव में क्या करता है। स्केलर प्रकारों के लिए, डिफ़ॉल्ट प्रारंभिकरण कुछ भी नहीं करता है, और असाइनमेंट वैल्यू से प्रारंभिकता के समान ही होता है, इसलिए दोनों विकल्प बराबर होंगे।

संबंधित मुद्दे