7

मेरे छोटे परीक्षणों के मुताबिक यह कोड काम करता है। लेकिन, क्या यह अपरिभाषित व्यवहार है? Const_cast के उपयोग के माध्यम से कॉन्स्ट ऑब्जेक्ट को संशोधित करने के परिणामस्वरूप मेरे पिछले परीक्षणों में रन-टाइम एक्सेस उल्लंघनों का परिणाम हुआ, लेकिन मुझे याद नहीं है कि वे अलग कैसे थे। तो, क्या मूल रूप से कुछ गलत है या नहीं?क्या const constcast के माध्यम से इस कॉन्स्ट प्रारंभिकता में अपरिभाषित व्यवहार है?

// test.h 
#pragma once 
#include <boost/array.hpp> 

typedef boost::array<int,100000> bigLut_t; 
extern const bigLut_t constBigLut; 

// test.cpp 
#include "test.h" 

bigLut_t& initializeConstBigLut() 
{ 
    bigLut_t* pBigLut = const_cast<bigLut_t*>(&constBigLut); 

    for(int i = 0; i < 100000; ++i) { 
     pBigLut->at(i) = i; 
    } 
    return const_cast<bigLut_t&>(constBigLut); 
} 

const bigLut_t constBigLut = initializeConstBigLut(); 

// const_test.cpp 
#include <iostream> 
#include "test.h" 

void main() 
{ 
    for(int i = 0; i < 100; ++i) { 
     std::cout << constBigLut[i] << std::endl; 
    } 
    system("pause"); 
} 

(ध्यान दें कि sizeof (bigLut_t) ढेर में फिट बहुत ज्यादा है।)

संपादित करें: मैं वास्तव में ybungalobill के दशक में विचार की तरह इन बड़ी वस्तुओं को शुरू करने की विधि के लिए सबसे छोटी टिप्पणी:

// test.h 
#pragma once 
#include <boost/array.hpp> 

extern const struct BigLut : public boost::array<int,100000> { 
    BigLut(); 
} constBigLut; 

// test.cpp 
#include "test.h" 

const BigLut constBigLut; 
BigLut::BigLut() 
{ 
    for(int i = 0; i < 100000; ++i) { 
     this->at(i) = i; 
    } 
} 
+6

:

आप ऐसा कर सकता है। 'मुख्य' ** हमेशा ** वापसी प्रकार 'int' होना चाहिए। हालांकि, आप 'वापसी' कथन को सुरक्षित रूप से छोड़ सकते हैं। –

उत्तर

6

आप एक वस्तु स्थिरांक के रूप में परिभाषित संशोधित करते हैं। इससे कोई फर्क नहीं पड़ता कि जब आप इसे प्रारंभ करते हैं या नहीं, यह अभी भी अपरिभाषित व्यवहार है। Const_cast के साथ स्थिरता को हटाकर केवल तभी परिभाषित किया जाता है जब किसी पूर्व चरण में उस ऑब्जेक्ट में किसी नॉन-कॉन्स्ट पॉइंटर से कॉन्स्ट पॉइंटर प्राप्त किया गया हो। यह तुम्हारा मामला नहीं है।

सबसे अच्छी बात आप कर सकते हैं

const bigLut_t& initializeConstBigLut() 
{ 
    static bigLut_t bigLot; 

    for(int i = 0; i < 100000; ++i) { 
     bigLut.at(i) = i; 
    } 
    return bigLut; 
} 

const bigLut_t constBigLut = initializeConstBigLut(); 

है और उम्मीद है कि संकलक स्थिर अस्थायी बाहर अनुकूलित करेंगे।

3

आप const_cast ऑपरेटर जो दुर्भाग्य से संभव है का दुरुपयोग कर रहे हैं, और इस मामले में अपरिभाषित व्यवहार उत्पन्न करता है ... आप अपने निहित प्रतिलिपि निर्माता (यह मानते हुए कि boost::arraystd::array रूप में एक ही अवधारणा है) लागू द्वारा constBigLut के लिए गतिशील प्रारंभकर्ता उपयोग कर सकते हैं:

struct bigLut_tinit { 
    bigLut_t BigLut; 

    bigLut_tinit() { 
    for(int i = 0; i < 100000; ++i) { 
     BigLut[i] = i; 
    } 
    } 
}; 

const bigLut_tinit constBigLut; 

संपादित करें: लगता है कि कुलपति ++ 10 पूरी तरह से RVO लागू होता है, तो यह है कि अस्थायी सीधे स्थिर अवधि वस्तु में ले जाया जाता है। तो इम्हो को स्थानीय सांख्यिकी या धर्मों के संदर्भों की घोषणा करने की आवश्यकता नहीं है ...

संपादित करें 2: हाँ, मुझे आकार की समस्या याद आई। ऊपर के रूप में कन्स्ट्रक्टर के साथ एक गैर-तुच्छ प्रकार में लपेटने की सिफारिश करें ...

+0

ओपी ने स्पष्ट रूप से कहा कि "आकार (bigLut_t) ढेर में फिट करने के लिए बहुत अधिक है।" संरचना विचार के लिए – ybungalobill

+1

+1। असल में आप इसे और भी बेहतर बना सकते हैं: संरचना को bigLut_t से प्राप्त करें, और फिर constBigLut का उपयोग कर कोड को अनचाहे किया जाएगा। – ybungalobill

+0

असल में मैं ऐसा कुछ नहीं करूँगा ... स्थिर अवधि की वस्तुओं को केवल एक असाधारण आपातकालीन समाधान होना चाहिए। फॉर्म 'std :: array' व्युत्पन्न करने से यह 'हैकर' IMHO भी बन जाएगा, क्योंकि यह स्पष्ट रूप से विरासत के उद्देश्य का उल्लंघन करेगा। अगर ऐसा कुछ आवश्यक हो जाता है, तो आपके पास शायद कुछ प्रकार की वास्तुशिल्प समस्या होगी, जिसे पहले हल किया जाना चाहिए।यदि यह काम नहीं करता, 'तरह bigLut_tinit' उदाहरण कुछ एक सुरक्षित सिंगलटन में, लपेट इतना है कि यह आगे का दुरुपयोग नहीं किया जा सकता है ... –

1

यह एक यूबी है, क्योंकि उस सरणी को रोम में संग्रहीत किया जा सकता है। बाकी, `शून्य main` सी में गैर कानूनी है ++ के अलावा

// test.h 
#include <boost/array.hpp> 

typedef boost::array<int,100000> bigLut_t; 
const bigLut_t& Lut(); 


// test.cpp 
#include "test.h" 

bool initialized=false; 

const bigLut_t& Lut() 
{ 
    static bigLut_t lut; 

    if (!initialized) 
    { 
    for(int i = 0; i < 100000; ++i) { 
     lut.at(i) = i; 
    } 
    } 
    return lut; 
} 
संबंधित मुद्दे