2009-06-05 8 views
8

मान लें कि मेरे पास एक ऑब्जेक्ट Employee_Storage है जिसमें डेटाबेस कनेक्शन डेटा सदस्य है। क्या इस डेटा सदस्य को सूचक के रूप में या संदर्भ के रूप में संग्रहीत किया जाना चाहिए?डेटा सदस्यों को पॉइंटर्स के बजाय संदर्भ के रूप में स्टोर करना बेहतर क्यों है?

  • अगर मैं एक संदर्भ के रूप में संग्रहीत, मैं किसी भी NULL जाँच करने के लिए की जरूरत नहीं है । (वैसे भी जाँच अभी कितना महत्वपूर्ण शून्य है?)

  • अगर मैं एक सूचक के रूप में संग्रहीत है, यह परीक्षण के प्रयोजनों के लिए सेटअप Employee_Storage (या MockEmployee_Storage) करना आसान है।

आम तौर पर, मैं हमेशा अपने डेटा सदस्यों को संदर्भ के रूप में संग्रहीत करने की आदत में रहा हूं। हालांकि, इससे मेरी नकली वस्तुओं को स्थापित करना मुश्किल हो जाता है, क्योंकि NULL एस (संभावित रूप से एक डिफ़ॉल्ट कन्स्ट्रक्टर के अंदर) में जाने में सक्षम होने के बजाय अब मुझे सच्चे/नकली वस्तुओं में गुजरना होगा।

क्या अंगूठे का पालन करने का अच्छा नियम है, विशेष रूप से टेस्टेबिलिटी की ओर नजर रखते हुए?

उत्तर

10

यदि वे निर्माण में असाइन किए जा रहे हैं तो डेटा सदस्यों के रूप में संदर्भों को स्टोर करना बेहतर है, और वास्तव में उन्हें बदलने का कोई कारण नहीं है। चूंकि संदर्भों को फिर से सौंपे नहीं जा सकते हैं, वे बहुत सीमित हैं।

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

+0

केवल संदर्भों का उपयोग करने के बारे में अपने बिंदु के बारे में जब कभी उन्हें बदलने का कोई कारण नहीं है - क्या मैं एक कॉन्स्ट पॉइंटर का उपयोग करके पॉइंटर्स के साथ एक ही चीज़ नहीं कर सकता? (ऑब्जेक्ट * कॉन्स m_ptr <- यह सूचक नहीं बदला जा सकता है।) यदि ऐसा है, तो ऐसा लगता है कि संदर्भों का उपयोग करने के कारण भी कम हैं ... – Runcible

+0

@Runcible: सच है, हालांकि संदर्भों का उपयोग थोड़ा सा है पॉइंटर सदस्यों के उपयोग से "अच्छा", इसलिए यदि आप वास्तव में उस व्यवहार को चाहते हैं, तो संदर्भ अक्सर काम करने के लिए क्लीनर होते हैं। मैं सदस्यों के लिए बहुत ही कम संदर्भ का उपयोग करता हूं, हालांकि - ज्यादातर मामलों में यह बहुत ही लचीला है। –

+0

मैं देखता हूं। और नल की जांच के बारे में क्या? यह देखते हुए कि आप पॉइंटर सदस्यों का उपयोग कर रहे हैं, क्या आपको जगह पर पूरी तरह से जांच करनी है? मुझे बताया गया है कि बहुत अधिक नल जांच सिर्फ पैरानोइड प्रोग्रामिंग और अतिरिक्त कोड ब्लोट के लिए है। मैं उत्सुक हूं कि आपका दृष्टिकोण क्या है। – Runcible

7

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

इस प्रश्न को और अधिक विस्तृत चर्चा के लिए इस प्रश्न को Should I prefer pointers or references in member data? देखें।

2

एक विकल्प को देखते हुए, मुझे सबसे अधिक बाध्य प्रकार का उपयोग करना पसंद है। तो अगर मैं अशक्त वस्तुओं मैं बहुत, एक

Foo*const m_foo; 

सदस्य के बजाय एक

Foo& m_foo; 

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

इसी तरह के प्रभाव को प्राप्त करने के अन्य तरीके हैं। एक प्रोजेक्ट जिस पर मैंने काम किया था, जहां उन्होंने संदर्भों को समझ नहीं लिया था, किसी भी संभावित नल पॉइंटर्स को '00' जैसे m_foo00 पर जोर दिया जाएगा। दिलचस्प बात यह है कि boost::optionalsupport references पर लगता है हालांकि मैंने इसे आजमाया नहीं है। या आप अपने कोड को दावे के साथ कूड़े कर सकते हैं।

3

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

#include <iostream> 
using namespace std; 
class stuff 
{ 
public: 
explicit stuff(int &a):x(a) //you have to initialize it here 
{ 
//body intialization won't work 
}; 
int& x; //reference data member 
}; 

int main() 
{ 
int A=100; 
stuff B(A);//intialize B.x 
cout<<B.x<<endl;//outputs 100 
A=50;//change A; 
cout<<B.x<<endl; //outputs 50, so B.x is an alias of A. 
system("pause"); 
return 0; 
} 
+0

यह होगा वही यदि आप इसे स्थानीय चर ए के लिए सूचक के रूप में पास करते हैं। – Tebe