2011-08-08 21 views
7

का कोड_कैस्ट निम्नलिखित कोड जीसीसी (4.2-4.6) और क्लैंग (2.1) के साथ दोनों को संकलित करता है, लेकिन जब मैं निष्पादन योग्य चलाता हूं तो यह मुझे "बस त्रुटि: 10" देता है। मुझे कारण समझ में नहीं आता है।स्थिर स्थिर सदस्य

#include <iostream> 

struct A 
{ 
    static int const v; 
    A() { ++*const_cast<int *>(&A::v); } 
}; 

int const A::v = 0; 

int main(int argc, char * argv[]) 
{ 
    A a, b, c; 
    std::cout << a.v << std::endl; 

    return 0; 
} 
+3

मुझे पूरा यकीन है कि आप जिस चीज को घोषित करते हैं उसे संशोधित करना अनिर्धारित व्यवहार है, लेकिन मुझे यकीन है कि कोई सटीक बयान खोद सकता है। कम से कम पूर्ण नमूना कार्यक्रम प्रदान करने के लिए –

+3

+1। अधिक जानकारी के लिए, http://sscce.org/ देखें। –

उत्तर

12

मुझे लगता है कि प्रासंगिक उद्धरण है:

§ 7.1.6.1 (4) from N3242:

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

उदाहरण const_cast का उपयोग कर बिंदु को वर्णन। जैसा कि जेम्स ने बताया: उद्धरण C++ 03 मानक में §7.1.5 में पाया जा सकता है।

थोड़ा सा विस्तार: वह भाषा नियम संकलक को केवल पढ़ने योग्य स्मृति (यदि यह लक्ष्य आर्किटेक्चर पर उपलब्ध है) का उपयोग करने की अनुमति देता है जब कुछ const घोषित किया जाता है। इस नियम के बिना const-किसी भी परिणाम से डरने के बिना हमेशा कास्ट किया जा सकता है और इसका उपयोग केवल डेवलपर अनुशासन का विषय होगा। जिस तरह से आप कम से कम लोगों को बता सकते हैं कि वे यूबी का आह्वान कर रहे हैं, जो आमतौर पर एक अच्छा निवारक होता है। const_cast स्वयं मामूली प्रासंगिकता का है क्योंकि इससे कोई फर्क नहीं पड़ता कि आप const ऑब्जेक्ट में हेरफेर करने में संकलक कैसे करते हैं।

4

क्योंकि आपको कॉन्स्ट के रूप में घोषित चर को संशोधित करने की अनुमति नहीं है।

2

मेरे पास वास्तविक समस्या का समाधान नहीं है। मैं बस कह सकता हूं, const_cast का उपयोग न करें जब तक कि किसी नॉन-कॉन्स्ट सदस्य फ़ंक्शन से कॉन्स्ट सदस्य फ़ंक्शन को कॉल करना और "const_cast" कॉन्स्ट परिणाम (गैर-कॉन्स्ट सदस्य फ़ंक्शन के लिए इसे एक उत्परिवर्तनीय परिणाम बनाने के लिए) का इरादा न करें।

लेकिन मैं अपने डिजाइन में सुधार लाने के लिए एक प्रस्ताव है:

class A 
{ 
private: 
    static int v; 
public: 
    A() { ++v; } 
    static int get_v() { return v; } 
}; 

int A::v = 0; 

int main(int argc, char * argv[]) 
{ 
    A a, b, c; 
    std::cout << a.get_v() << std::endl; 

    return 0; 
} 
1

समस्या इस लाइन है:

static int const v; 

क्योंकि आप इसे स्थिरांक की घोषणा की, const_cast एक अपरिभाषित व्यवहार उत्पन्न कर रहा है - अपनी यदि आप बस त्रुटि प्राप्त करने के साथ भाग्यशाली हैं (यह मेरे सिस्टम पर एक सेगमेंटेशन गलती है)।

इसे गैर-कॉन्स घोषित करें, और आप समस्याओं के बिना const_cast पर कॉल कर सकते हैं।

2

सिर्फ इसलिए कि आपने दूर कास्ट डाला है, इसका मतलब यह नहीं है कि आप उस स्मृति को लिखने में सफल होंगे।

सभी const_cast<T> संकलक के परिप्रेक्ष्य से चर के कॉन्स्ट-नेस को हटा देता है। इससे कंपाइलर आगे बढ़ने और चर को लिखने के लिए कोड उत्सर्जित करने देता है। लेकिन रनटाइम पर, यदि कंपाइलर/लिंकर वैरिएबल को रीड-ओनली मेमोरी में डालता है, तो हार्डवेयर आपको लिखने से रोक देगा, चाहे आप इसे कैसे फेंक दें।

6

5.2.11.7:

Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier) may produce undefined behavior (7.1.5.1)

आपके मामले में, आप डेटा केवल पढ़ने के क्षेत्र में है कि संशोधित करने के लिए कोशिश कर रहे हैं।

+1

यह एक गैर-मानक नोट है (यानी यह केवल सूचनात्मक है)। मानक पाठ संदर्भित §7.1.5.1 पर है। –

+0

मसौदे में यह §7.1.6.1 है। मेरा जवाब देखें – pmr

+1

@pmr: ठीक है, क्योंकि C++ 0x spec 'constexpr' को परिभाषित करने वाला एक खंड जोड़ता है। –

2

असल में, यदि एक चर को const घोषित किया गया है, तो संकलक को परिणामों को केवल स्मृति पढ़ने के लिए उत्सर्जित करने की अनुमति है। const ऑब्जेक्ट के पॉइंटर/संदर्भ लेना और const को हटाने के लिए const_cast का उपयोग करके अपरिभाषित व्यवहार हो सकता है।

सामान्यतः, const_cast का उपयोग करने के लिए केवल सुरक्षित है यदि ऑब्जेक्ट को फिर से पेश किया जा रहा है, तो गैर-const (भले ही आपके पास पॉइंटर/संदर्भ const है)।

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