2009-03-31 19 views
6

मैं सी में प्रोग्रामिंग किया गया है थोड़ी देर के ++ और मैं दोनों तरीकों का उपयोग किया है:रचनाकारों में शुरूआत, सर्वोत्तम अभ्यास?

class Stuff { 
public: 
    Stuff(int nr) : n(nr) { } 
private: 
    int n; 
} 

या

class Stuff { 
public: 
    Stuff(int nr) { 
     n = nr; 
    } 
private: 
    int n; 
} 

नोट: यह this, समान, लेकिन एक ही नहीं के रूप में ही नहीं है।

सर्वोत्तम अभ्यास माना जाता है?

उत्तर

21

प्रारंभकर्ता सूचियों को प्राथमिकता दी जाती है। देखें FAQ 10.6

+2

उस लिंक पर एक वर्जित हो रही है। मुझे लगता है कि यही कारण है कि लिंक केवल जवाब निराश हैं। – wvdz

+0

यहां वर्तमान लिंक है जो बताता है कि क्यों प्रारंभकर्ता सूचियों को प्राथमिकता दी जाती है। https://isocpp.org/wiki/faq/ctors#init-lists – NigoroJr

5

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

प्लस, आपको इसे किसी भी तरह से कॉन्स्ट सदस्यों या सदस्यों के लिए करना है जिनके पास डिफ़ॉल्ट कन्स्ट्रक्टर नहीं है।

+2

संदर्भ सदस्यों के लिए इनिट सूची का उपयोग करना भी आवश्यक है। –

2

यदि संभव हो, तो पहले संस्करण का उपयोग करें।

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

दूसरा असाइनमेंट है। यदि एन एक डिफ़ॉल्ट कन्स्ट्रक्टर के साथ एक प्रकार का था, तो इसे पहले से ही बुलाया जाएगा, और फिर आप इसे असाइन करेंगे। अगर एन में डिफॉल्ट कन्स्ट्रक्टर नहीं है, तो आपको पहले प्रकार का उपयोग करने के लिए मजबूर होना होगा। इसी प्रकार यदि एन संदर्भ था: int &n

यदि आपके सदस्यों के कोई निर्माता नहीं हैं जो सीधे आपके कन्स्ट्रक्टर को पैरामीटर में से एक लेते हैं, तो निजी स्थिर फ़ंक्शंस जोड़ने के लिए उपयोगी हो सकता है जो आपके लिए रूपांतरण कर सकते हैं।

1

मैं आम तौर पर जब मैं कर सकता हूं प्रारंभकर्ता सूची करने की कोशिश करता हूं। एक बात के लिए, यह स्पष्ट करता है कि आप कन्स्ट्रक्टर में कोड प्रारंभ कर रहे हैं। कॉन्स मेम्बर इस तरह से शुरू करने के लिए है।

यदि आप केवल कन्स्ट्रक्टर के शरीर में कोड डालते हैं, तो यह संभव है कि कोई भी साथ आने और एक गैर-कन्स्ट्रक्टर "सेटअप" दिनचर्या में इसके बड़े हिस्से को स्थानांतरित करने का निर्णय ले सके।

हालांकि इसे ओवरबोर्ड पर लिया जा सकता है। मेरे पास एक सहकर्मी है जो कक्षाएं बनाना पसंद करता है जिसमें इनिटिलाइज़र कोड के 2 पृष्ठ, कोई कन्स्ट्रक्टर कोड नहीं है, और संभवतः कक्षा के पूरे शेष कोड के लिए 2 पृष्ठ हैं। मुझे लगता है कि पढ़ने के लिए वास्तव में मुश्किल है।

0

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

कुछ प्रकार डिफ़ॉल्ट रूप से प्रारंभ नहीं किए जा सकते हैं: यदि आपके पास डिफ़ॉल्ट कन्स्ट्रक्टर के बिना कोई विशेषता है, तो संदर्भ (स्थिर या नहीं) रखें या निरंतर विशेषताओं को प्रारंभिक सूची में प्रारंभ किया जाना चाहिए।

सरणी मूल्य प्रारंभ प्रारंभ सूची में हो सकता है, लेकिन निर्माता शरीर में नहीं:

class X { 
public: 
    X() : array() {} // value-initializes the array 
// equivalent to: 
// X() { for (int i = 0; i < 10; ++i) array[i]=0; }  
private: 
    int array[10]; 
}; 

पॉड प्रकार के लिए, आप कर सकते हैं प्रारंभ सूची में उन्हें मूल्य आरंभ कर देगा लेकिन कोष्ठक के अंदर नहीं:

class X { 
public: 
    X() : pod() {} // value-initializes 
// equivalent to (but easier to read and subtly faster as it avoids the copy): 
// X() { pod = {}; } 
private: 
    PODType pod; 
}; 

अंत में, कुछ कक्षाएं रचनाकारों के उपयोग के माध्यम से कार्यक्षमता प्रदान करती हैं जो डिफ़ॉल्ट निर्माण के बाद अधिक जटिल (यदि प्राप्त करने योग्य) होगी।

class X 
{ 
public: 
    X() : v(10) {} // construct a vector of 10 default initialized integers 
// equivalent to: 
// X() { for (int i = 0; i < 10; ++i) v.push_back(0); } 
private: 
    std::vector<int> v; 
}; 

अंतिम, जब भी वे वास्तव में समकक्ष होते हैं, प्रारंभिक सूचियां सी ++ में अधिक मूर्खतापूर्ण होती हैं।

12

प्रारंभकर्ताओं का उपयोग करने के लिए एक बड़ा फायदा: अगर किसी अपवाद को प्रारंभकर्ता सूची में कहीं भी फेंक दिया जाता है, तो विनाशकों को उन सदस्यों के लिए बुलाया जाएगा जिन्हें पहले से ही शुरू किया गया था - और केवल उन सदस्यों के लिए।

जब आप ऑब्जेक्ट को प्रारंभ करने के लिए कन्स्ट्रक्टर बॉडी का उपयोग करते हैं, तो अपवादों को सही तरीके से संभालने और ऑब्जेक्ट को उचित रूप से खोलने के लिए आप पर निर्भर है। यह आमतौर पर सही होने के लिए बहुत कठिन है।

0

मैं यह जोड़ना चाहता हूं कि आपको शीर्षलेख (.h) पर प्रारंभकर्ता सूची घोषित करने की आवश्यकता नहीं है। यह कन्स्ट्रक्टर के कार्यान्वयन पर किया जा सकता है (जो बहुत आम है)।

तो फिर:

//Stuff.h 
class Stuff { 
public: 
    Stuff(int nr); 
private: 
    int n; 
} 

//Stuff.cpp 
Stuff::Stuff(int nr) 
: n(nr) 
{ 
    //initalize complex members 
} 

कानूनी है और imo क्षेत्रों जहां यह मायने रखता है के प्रारंभ केंद्रित है। कभी-कभी हमें शरीर में जटिल सदस्यों को प्रारंभ करने की आवश्यकता होती है, इसलिए आपके पास प्रारंभिक सूची और जटिल प्रारंभिकता सभी .cpp फ़ाइल में होती है।

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