आंतरिक रूप से और उत्पन्न कोड के बारे में, क्या वास्तव में अंतर है:
MyClass::MyClass(): _capacity(15), _data(NULL), _len(0)
{
}
तथा
MyClass::MyClass()
{
_capacity=15;
_data=NULL;
_len=0
}
धन्यवाद...
जवाबों:
यह मानते हुए कि वे मूल्य आदिम प्रकार हैं, तो नहीं, कोई अंतर नहीं है। आरंभिक सूचियों में केवल तभी फर्क पड़ता है जब आपके पास सदस्य के रूप में ऑब्जेक्ट्स होते हैं, क्योंकि असाइनमेंट के बाद डिफ़ॉल्ट आरंभीकरण का उपयोग करने के बजाय, प्रारंभिक सूची आपको ऑब्जेक्ट को उसके अंतिम मूल्य पर आरंभीकृत करने देती है। यह वास्तव में काफ़ी तेज़ हो सकता है।
आपको निरंतर सदस्यों, संदर्भों और आधार वर्ग को आरंभ करने के लिए आरंभीकरण सूची का उपयोग करने की आवश्यकता है
जब आपको निरंतर सदस्य को संदर्भित करने की आवश्यकता होती है, तो बेस निर्माणकर्ताओं को संदर्भ और पास पैरामीटर, जैसा कि टिप्पणियों में बताया गया है, आपको आरंभीकरण सूची का उपयोग करने की आवश्यकता है।
struct aa
{
int i;
const int ci; // constant member
aa() : i(0) {} // will fail, constant member not initialized
};
struct aa
{
int i;
const int ci;
aa() : i(0) { ci = 3;} // will fail, ci is constant
};
struct aa
{
int i;
const int ci;
aa() : i(0), ci(3) {} // works
};
उदाहरण (गैर-थकावट) वर्ग / संरचना में संदर्भ शामिल हैं:
struct bb {};
struct aa
{
bb& rb;
aa(bb& b ) : rb(b) {}
};
// usage:
bb b;
aa a(b);
और आधार वर्ग को आरम्भ करने का उदाहरण जिसके लिए एक पैरामीटर की आवश्यकता होती है (उदाहरण के लिए कोई डिफ़ॉल्ट निर्माता नहीं):
struct bb {};
struct dd
{
char c;
dd(char x) : c(x) {}
};
struct aa : dd
{
bb& rb;
aa(bb& b ) : dd('a'), rb(b) {}
};
_capacity
, _data
और _len
एक सुलभ डिफ़ॉल्ट निर्माणकर्ताओं के बिना वर्ग प्रकार हैं?
const
कंस्ट्रक्टर के शरीर में सदस्य को इनिशियलाइज़ नहीं कर सकते , आपको इनिशियलाइज़ेशन लिस्ट का उपयोग करना होगा - नॉन const
मेंबर्स को इनिशियलाइज़ेशन लिस्ट में या कंस्ट्रक्टर के बॉडी में इनिशियलाइज़ किया जा सकता है।
हाँ। पहले मामले में आप घोषणा कर सकते हैं _capacity
, _data
और _len
स्थिरांक के रूप में:
class MyClass
{
private:
const int _capacity;
const void *_data;
const int _len;
// ...
};
यह महत्वपूर्ण होगा यदि आप const
रनटाइम के दौरान अपने मूल्यों की गणना करते समय इन उदाहरण चरों की सुनिश्चित करना चाहते हैं , उदाहरण के लिए:
MyClass::MyClass() :
_capacity(someMethod()),
_data(someOtherMethod()),
_len(yetAnotherMethod())
{
}
const
उदाहरणों को प्रारंभिक सूची में आरंभीकृत किया जाना चाहिए या अंतर्निहित प्रकारों को सार्वजनिक पैरामीटर रहित कंस्ट्रक्टर (जो आदिम प्रकार करते हैं) प्रदान करना होगा।
मुझे लगता है कि यह लिंक http://www.cplusplus.com/forum/articles/17820/ एक उत्कृष्ट व्याख्या देता है - विशेष रूप से C ++ के लिए उन लोगों के लिए।
कारण यह है कि इंटेस्टाइज़र सूचियां अधिक कुशल हैं, यह कि कंस्ट्रक्टर बॉडी के भीतर केवल असाइनमेंट होते हैं, इनिशियलाइज़ेशन नहीं। इसलिए यदि आप एक गैर-बिल्ट-इन प्रकार के साथ काम कर रहे हैं, तो उस ऑब्जेक्ट के लिए डिफ़ॉल्ट कंस्ट्रक्टर को पहले ही कहा जा चुका है कि कंस्ट्रक्टर के शरीर में प्रवेश किया जा चुका है। कंस्ट्रक्टर बॉडी के अंदर, आप उस ऑब्जेक्ट को एक मान दे रहे हैं।
वास्तव में, यह डिफॉल्ट कंस्ट्रक्टर के लिए एक कॉल है जिसके बाद कॉपी-असाइनमेंट ऑपरेटर को कॉल किया जाता है। प्रारंभिक सूची आपको प्रतिलिपि निर्माता को सीधे कॉल करने की अनुमति देती है, और यह कभी-कभी काफी तेज हो सकता है (याद रखें कि प्रारंभिक सूची निर्माणकर्ता के शरीर से पहले है)
मुझे लगता है कि यदि आपके पास कोई डिफ़ॉल्ट निर्माता उपलब्ध वर्ग प्रकार के सदस्य हैं, तो आरंभीकरण आपके वर्ग के निर्माण का एकमात्र तरीका है।
एक बड़ा अंतर यह है कि असाइनमेंट एक मूल वर्ग के सदस्यों को शुरू कर सकता है; इनिशियलाइज़र केवल वर्तमान वर्ग के दायरे में घोषित सदस्यों पर काम करता है।
शामिल प्रकारों पर निर्भर करता है। अंतर के बीच समान है
std::string a;
a = "hai";
तथा
std::string a("hai");
जहाँ दूसरा रूप इनिशियलाइज़ेशन लिस्ट है- यानी, अगर कंस्ट्रक्टर तर्कों के लिए टाइप की आवश्यकता है या कंस्ट्रक्शन तर्कों के साथ अधिक कुशल है तो इससे फर्क पड़ता है।
वास्तविक अंतर यह है कि कैसे जीसीसी संकलक मशीन कोड उत्पन्न करता है और मेमोरी को नीचे ले जाता है। के बारे में बताएं:
कॉन्स्ट टाइप सदस्यों को संभालने के लिए निश्चित रूप से अन्य तरीके हैं। लेकिन उनके जीवन को आसान बनाने के लिए, gcc संकलक लेखक कुछ नियम निर्धारित करते हैं
बेस क्लास इंस्टेंसेस और नॉन-स्टैटिक मेंबर वेरिएबल्स को इनिशियलाइज़ करने का एक ही तरीका है और वह है इनिशियलाइज़र लिस्ट।
यदि आप अपने निर्माता की प्रारंभिक सूची में एक आधार या गैर-स्थैतिक सदस्य चर निर्दिष्ट नहीं करते हैं, तो वह सदस्य या आधार या तो डिफ़ॉल्ट-प्रारंभिक हो जाएगा (यदि सदस्य / आधार गैर-पीओडी वर्ग प्रकार या गैर-पीओडी वर्ग का सरणी है) प्रकार) या अन्यथा असंवैधानिक छोड़ दिया है।
एक बार निर्माणकर्ता के शरीर में प्रवेश करने के बाद, सभी ठिकानों या सदस्यों को आरंभिक या छोड़ दिया गया होगा (यानी उनका अनिश्चित मान होगा)। निर्माणकर्ता निकाय में यह प्रभावित करने का कोई अवसर नहीं है कि उन्हें कैसे आरंभ किया जाए।
आप कंस्ट्रक्टर बॉडी में सदस्यों के लिए नए मान निर्दिष्ट करने में सक्षम हो सकते हैं, लेकिन उन const
सदस्यों या सदस्यों को वर्ग प्रकार के लिए असाइन करना संभव नहीं है जिन्हें गैर-असाइन किया गया है और यह संदर्भों को फिर से बनाना संभव नहीं है।
निर्मित प्रकारों और कुछ उपयोगकर्ता-परिभाषित प्रकारों के लिए, कंस्ट्रक्टर बॉडी में असाइन करना बिल्कुल वैसा ही प्रभाव हो सकता है जैसा कि इनिशियलाइज़र सूची में समान मूल्य के साथ इनिशियलाइज़ करना।
यदि आप किसी सदस्य या आधार का नाम इनिशियलाइज़र सूची में रखने में विफल रहते हैं और वह इकाई एक संदर्भ है, जिसमें कोई सुलभ उपयोगकर्ता-घोषित डिफ़ॉल्ट निर्माता के साथ वर्ग प्रकार है, const
योग्य है और उसमें POD प्रकार है या POD वर्ग प्रकार या POD वर्ग प्रकार की सरणी है एक const
योग्य सदस्य (प्रत्यक्ष या अप्रत्यक्ष रूप से) से युक्त है, तो कार्यक्रम बीमार है।
यदि आप एक प्रारंभिक सूची लिखते हैं, तो आप सभी एक ही चरण में करते हैं; यदि आप एक initilizer सूची नहीं लिखते हैं, तो आप 2 चरण करेंगे: एक घोषणा के लिए और एक मान के लिए।
एक कंस्ट्रक्टर में इनिशियलाइज़ेशन लिस्ट और इनिशियलाइज़ेशन स्टेटमेंट के बीच अंतर होता है। आइए नीचे दिए गए कोड पर विचार करें:
#include <initializer_list>
#include <iostream>
#include <algorithm>
#include <numeric>
class MyBase {
public:
MyBase() {
std::cout << __FUNCTION__ << std::endl;
}
};
class MyClass : public MyBase {
public:
MyClass::MyClass() : _capacity( 15 ), _data( NULL ), _len( 0 ) {
std::cout << __FUNCTION__ << std::endl;
}
private:
int _capacity;
int* _data;
int _len;
};
class MyClass2 : public MyBase {
public:
MyClass2::MyClass2() {
std::cout << __FUNCTION__ << std::endl;
_capacity = 15;
_data = NULL;
_len = 0;
}
private:
int _capacity;
int* _data;
int _len;
};
int main() {
MyClass c;
MyClass2 d;
return 0;
}
जब MyClass का उपयोग किया जाता है, तो एक कंस्ट्रक्टर निष्पादित किए गए पहले कथन से पहले सभी सदस्यों को आरंभीकृत किया जाएगा।
लेकिन, जब MyClass2 का उपयोग किया जाता है, तो सभी सदस्यों को आरंभिक नहीं किया जाता है जब एक निर्माणकर्ता के पहले कथन को निष्पादित किया जाता है।
बाद के मामले में, किसी व्यक्ति द्वारा एक निश्चित सदस्य को इनिशियलाइज़ किए जाने से पहले कंस्ट्रक्शन में कुछ कोड जोड़ने पर रिग्रेशन की समस्या हो सकती है।
यहाँ एक बिंदु यह है कि मैंने दूसरों को इसका उल्लेख करते नहीं देखा:
class temp{
public:
temp(int var);
};
अस्थायी वर्ग में एक डिफ़ॉल्ट ctor नहीं है। जब हम इसका अनुसरण दूसरी कक्षा में करते हैं:
class mainClass{
public:
mainClass(){}
private:
int a;
temp obj;
};
कोड संकलित नहीं करेगा, क्योंकि कंपाइलर को पता नहीं है कि कैसे इनिशियलाइज़ किया जाए obj
, क्योंकि इससे एक स्पष्ट ctor प्राप्त होता है, जो एक int value प्राप्त करता है, इसलिए हमें ctor को निम्नानुसार बदलना होगा:
mainClass(int sth):obj(sth){}
तो, यह केवल कास्ट और संदर्भों के बारे में नहीं है!