2012-12-16 35 views
7

निम्नलिखित कोड पर विचार करें:क्या संदर्भ में अस्थायी बाध्यकारी सी ++ में एक प्रतिलिपि बनाने की आवश्यकता है?

class A { 
    A(const A&); 
public: 
    A() {} 
}; 

int main() { 
    const A &a = A(); 
} 

इस कोड जीसीसी 4.7.2 के साथ ठीक संकलित है, लेकिन निम्न त्रुटि के साथ विजुअल C++ 2010 को संकलित करने में विफल रहता है:

test.cc(8) : error C2248: 'A::A' : cannot access private member declared in class 'A' 
     test.cc(2) : see declaration of 'A::A' 
     test.cc(1) : see declaration of 'A' 

तो यह है के लिए आवश्यक है संदर्भ में अस्थायी बाध्य करते समय एक प्रतिलिपि बनाने योग्य सुलभ है?

यह कुछ हद तक मेरे पिछले प्रश्न से संबंधित है:

Is there a way to disable binding a temporary to a const reference?

+0

हां, कॉपी सीटीआर निजी है और जानबूझकर लागू नहीं किया गया है। – vitaut

+0

क्या आपने अभी 'ए() की कोशिश की है। 'यह संभव है कि प्रतिलिपि बनाने के लिए प्रतिलिपि बनाने के लिए प्रतिलिपि बनाने की आवश्यकता हो। –

+0

विजुअल सी ++ 2012 कोड स्वीकार करता है। –

उत्तर

4

So is it necessary to have a copy constructor accessible when binding a temporary to a reference?

पोस्ट सी ++ 11 - कोई
पूर्व सी ++ 11 - हाँ।


यह कोड जीसीसी 4.7.2 के साथ ठीक से संकलित करता है क्योंकि यह सी ++ 11 मानक के अनुरूप है।

सी ++ 11 मानक जनादेश है कि जब एक कॉन्स्ट संदर्भ prvalue से प्रारंभ किया जाता है, तो इसे सीधे संदर्भ वस्तु से बाध्य होना चाहिए और कोई अस्थायी बनाने की अनुमति नहीं है। इसके अलावा, कॉपी कन्स्ट्रक्टर का उपयोग या आवश्यक नहीं है।

सी ++ 11 से पहले नियम अलग थे। और यह व्यवहार (चाहे प्रतिलिपि निर्माता को कहा जाएगा) कार्यान्वयन परिभाषित किया गया है। सी ++ 03 ने अस्थायी के लिए एक कॉन्स्ट संदर्भ को बाध्य करते समय कॉपी कन्स्ट्रक्टर को बुलाया और इसलिए सी ++ 11 पोस्ट करने के लिए कॉपी कन्स्ट्रक्टर को एक्सेस करने की आवश्यकता है। विज़ुअल सी ++ 2010 सी ++ 03 मानक का पालन करता है।

+0

"और यह व्यवहार कार्यान्वित किया गया था" थोड़ा भ्रामक है। वास्तविक प्रतिलिपि या कार्यान्वयन को परिभाषित नहीं किया गया था, लेकिन सी ++ 03 मानक के लिए एक सुलभ प्रतिलिपि बनाने की आवश्यकता थी। –

+0

@ चीयर्संधथ-अल्फ: इसे और अधिक स्पष्ट बनाने के लिए संपादित किया गया। –

+1

"सी ++ 11 मानक जनादेश देता है कि जब एक कॉन्स संदर्भ प्रक्षेपण से प्रारंभ किया जाता है, तो इसे सीधे संदर्भ वस्तु से बाध्य किया जाना चाहिए और कोई अस्थायी बनाने की अनुमति नहीं है।" हम थोड़ा भ्रामक। यह केवल तब होता है जब प्रकार ऐसे होते हैं कि प्रत्यक्ष बाध्यकारी संभव है। दूसरे शब्दों में, नियम एक रूपांतरण को रोक नहीं देते हैं। –

0

विजुअल C++ गलत है; मानक यह इंगित नहीं करता है कि कॉपी कन्स्ट्रक्टर को const अस्थायी संदर्भ के लिए बाध्य करने के लिए सुलभ होना चाहिए।

2

धारा सी ++ 03 मानक राज्यों के 8.5.3.5 कि इस कार्यान्वयन परिभाषित किया गया है:

If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation-defined):

-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

-- A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

तो ऐसा लगता है कि दोनों कार्यान्वयन सी ++ 03 मानक के अनुरूप हैं।

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

सी ++ 11 मानक के साथ, दूसरा तरीका अब एक विकल्प नहीं है।

+4

सी ++ 03 को सी ++ 11 द्वारा हटा दिया गया है और नियम C++ 11 में बदल गए हैं। –

+0

ठीक है, यही वह है जिसे मैं ढूंढ रहा था। धन्यवाद। – vitaut

+0

@ वॉन कैटो: केवल एक चीज यह है कि आपका अंतिम विवरण आपके द्वारा उद्धृत मानक से अंतिम बयान के विपरीत है। आईआईयूसी मानक कहता है कि कॉपी सीटीआर दोनों मामलों में उपलब्ध होना चाहिए, इसलिए जीसीसी नए मानक या उसके बग से नियमों का उपयोग कर सकता है। – vitaut