2011-01-31 5 views
7

क्या कक्षा के उदाहरणों को केवल राजस्व (जैसे अस्थायी) के रूप में उपयोग करना प्रतिबंधित है?कक्षा के उदाहरणों को केवल अस्थायी के रूप में इस्तेमाल करना संभव है?

उदाहरण के लिए, मेरे पास कक्षा Wrapper है जिसका निर्माता A const& लेता है और इस संदर्भ को इसके सदस्य में सहेजता है। यह एक खतरनाक है क्योंकि Wrapper का जीवनकाल A उदाहरण के जीवनकाल से अधिक नहीं हो सकता है, लेकिन यह ठीक है अगर Wrappertemporary है।

+1

क्या आप एम ईन केवल ढेर के बजाय ढेर पर उदाहरण बनाने की इजाजत देता है? –

+0

नहीं, केवल अस्थायी के रूप में। स्टैक –

+1

पर ऐसे उदाहरण बनाने के लिए अभी भी खतरनाक है कभी-कभी सबसे अच्छा निवारक दस्तावेज़ में "एक्स न करें" की टिप्पणी है। –

उत्तर

3

मुझे नहीं लगता कि यह सुरक्षित होगा:

const A &a = YourClass(tmp); 

YourClass इस मामले में वर्ग आप जिसके लिए केवल अस्थायी उदाहरणों की अनुमति देने के लिए देख रहे हैं, tmp अस्थायी मूल्य आप निर्माता के पास है।
यह संभव है (यानी: सुरक्षित, परिभाषित व्यवहार) एक अस्थायी (यानी: a) का निरंतर संदर्भ रखने के लिए, लेकिन अस्थायी स्वयं (YourClass का उदाहरण) tmp का संदर्भ मिला है जो उस अभिव्यक्ति के बाद मान्य नहीं है मूल्यांकन किया जाता है।

+0

बिल्कुल मैं क्या सोच रहा था। आप इसे वाक्य रचनात्मक रूप से कर सकते हैं, लेकिन तथ्य यह है कि आप इसे संदर्भित कर सकते हैं, इसके खतरनाक तरीके से इसके जीवनकाल को बढ़ाएंगे। – CashCow

0

हाँ, आप कर सकते हैं।

आप कन्स्ट्रक्टर और नियमित प्रति-कन्स्ट्रक्टर/निजी असाइन करेंगे लेकिन आर-वैल्यू मूव सेमेन्टिक्स (सी ++ 0 एक्स) सार्वजनिक करेंगे।

आपके पास अस्थायी बनाने के लिए एक स्थिर या मित्र निर्माता होगा।

2003 सी ++ में आप इसे एक कॉन्स्ट संदर्भ से बांधने के लिए उपयोग करने में भी सक्षम होंगे।

बेशक आपको यह मुद्दा होगा कि कथन के बाद आपका कॉन्स संदर्भ शायद अमान्य हो जाएगा।

+0

उम ... क्या आप वाकई काम करने जा रहे हैं? यदि एकमात्र सार्वजनिक कन्स्ट्रक्टर रावल्यू संदर्भ है, तो मुझे नहीं लगता कि आप अपनी कक्षा के किसी भी इंस्टेंस को तुरंत चालू कर पाएंगे - इस प्रकार आप कभी भी रावल्यू रेफरेंस कन्स्ट्रक्टर को एक उदाहरण पास नहीं कर पाएंगे .. – peoro

+0

वह सुझाव दे रहा था एक दोस्त फ़ंक्शन का उपयोग करना जो एक रावल्यू देता है। – Puppy

+2

यह 'टी कॉन्स्ट एंड रेफ = टी :: फैक्ट्री (ब्लाह) को नहीं रोकता है; ': ले जाएं अर्थशास्त्र एक रिटर्न-बाय-वैल्यू (जिसे elided किया जा सकता है) और कॉन्स और जीवन भर बढ़ाता है। मैं क्या खो रहा हूँ? –

1

मैं संकलन समय पर इस लागू करने, हम उसे नहीं परेशान, के रूप में वहाँ हमेशा वर्ग की उपयोगिता सीमित, कोने मामलों में जहां इस अधिक प्रतिबंधात्मक होगा होने जा रहे हैं, बल्कि valgrind या Purify जैसे उपकरणों लपेट तो मैं देखा जा सकता है वे स्थान जहां अमान्य संदर्भों का उपयोग किया जाता है।

3

मुझे लगता है कि यह भी करना चाहते हैं कि वास्तव में एक खराब डिजाइन का संकेत है।

हालांकि, आप सभी रचनाकारों को निजी बना सकते हैं और एक मित्र कार्य कर सकते हैं जो एक रैल्यू देता है। यह ट्रिक काम आना चाहिए।

+0

यह कैसे काम करेगा? या तो प्रतिलिपि ctor या move ctor मूल्य से वापस आने के लिए सुलभ होना चाहिए, भले ही वे elided हैं। –

+0

नहीं यदि वह संदर्भ द्वारा परिणाम ले रहा है। – Puppy

+0

यहां तक ​​कि संदर्भ द्वारा परिणाम लेते समय भी: http://codepad.org/97oaJNfl और N3225 §12.2p1, "... एक प्रक्षेपण के संदर्भ को बाध्यकारी, एक प्रावधान लौटा रहा है ... भले ही प्रतिलिपि/चालक कन्स्ट्रक्टर नहीं कहा जाता है, सभी पहुंच के रूप में अर्थपूर्ण प्रतिबंध, संतुष्ट होंगे। " –

3

बिल्कुल सही उत्तर नहीं जिसे आप ढूंढ रहे हैं, लेकिन क्या आपने कमजोर पॉइंटर्स के बारे में सोचा है? (उदाहरण के लिए, boost::weak_ptr)। इस मामले में, मूल Ashared_ptr में आयोजित किया जाएगा और Wrapper कन्स्ट्रक्टर weak_ptr स्वीकार करता है। इस दृष्टिकोण के साथ साफ बात यह है कि, weak_ptr के प्रत्येक उपयोग से पहले, आप lock() का प्रयास कर सकते हैं जो आपको shared_ptr देगा - यदि यह विफल हो जाता है, तो आप जानते हैं कि A चला गया है और Wrapper कार्य नहीं कर सकता ... लेकिन इसे साफ़ रूप से संभाला जाता है। ..

0

यह तब तक काम कर सकता है जब तक आपकी कक्षा में सार्वजनिक डेटा सदस्य न हों।

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

class Wrapper 
{ 
public: 
    Wrapper() = default; 
    Wrapper(const std::string& name) : name(name) {} 
    void process() && { std::cout << "Greetings from " << name << std::endl; } 
    // Only temporary instances of this class are allowed! 
    void process() const & = delete; 

private: 
    std::string name; 
}; 

और कुछ उपयोग के मामलों:

Wrapper("John").process(); // intended use case 
Wrapper j; // create whatever you want 
j.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function 
std::move(j).process(); // this is still possible 
const Wrapper& t = Wrapper(); // bind the temporary to a const reference - not a problem because ... 
t.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function 

स्पष्ट नुकसान कर रहे हैं:

  • आप ओवरलोड हर सार्वजनिक सदस्य कार्य हो

    यहाँ एक सरल उदाहरण है।

  • त्रुटि संदेश में देरी हो रही है और बहुत जानकारीपूर्ण नहीं है।

मानक में एक समान बात की गई है। Std :: context_wrapper do not accept temporaries के लिए मेक रूटीन।

नोट है कि वे एक और सूक्ष्मता माना: अधिभार स्थिरांक टी & & बजाय टी & & उपयोग करता है। यह हमारे मामले में भी महत्वपूर्ण हो सकता है। उदाहरण के लिए, यदि आपके आवरण जानबूझकर और noncopyable डिज़ाइन किया गया है आप इस तरह के

const Wrapper make_wrapper(); 
बजाय

Wrapper make_wrapper(); 

इस मामले में के रूप में दिनचर्या बनाने का उपयोग करें, आप को बदलने के लिए चाहते हो सकता है

void process() &&; 

void process() const &&; 
संबंधित मुद्दे

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