2010-01-09 17 views
17

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

int main() { 
    boost::array<int, 4> array = {{1,2,3,4}}; 
    MyClass obj(array); 
} 

class MyClass { 
    private: 
     boost::array<int, std::size_t> array; 
    public: 
     template<std::size_t N> MyClass(boost::array<int, N> array) 
     : array(array) {}; 
}; 

संकलक, जीसीसी, कहते हैं:

error: type/value mismatch at argument 2 in template parameter list for 
    ‘template<class _Tp, long unsigned int _Nm> struct boost::array’ 
error: expected a constant of type ‘long unsigned int’, got ‘size_t’ 

कौन सा स्पष्ट रूप से मतलब है कि एक वर्ग के सदस्यों के रूप में चर आकार सरणियों उपयोग नहीं कर सकते । यदि ऐसा है, तो यह वेक्टर या मानक सरणी पर boost :: सरणी के सभी फायदों को अस्वीकार कर देगा।

क्या आप मुझे दिखा सकते हैं कि मैंने क्या गलत किया?

उत्तर

19

बूस्ट के सरणी निश्चित आकार दूसरा टेम्पलेट पैरामीटर के आधार पर है, और boost::array<int,4>boost::array<int,2> से एक अलग प्रकार है। आपके पास एक ही कक्षा के उदाहरण नहीं हो सकते हैं (आपके उदाहरण में MyClass) जिसमें उनके सदस्यों के लिए अलग-अलग प्रकार हैं।

struct MyClass { 
    template<std::size_t N> 
    explicit 
    MyClass(boost::array<int, N> const& array) 
    : data(array.begin(), array.end()) 
    {} 

private: 
    std::vector<int> data; 
}; 

int main() { 
    boost::array<int, 4> a = {{1,2,3,4}}; 
    MyClass obj(a); 

    boost::array<int, 2> a2 = {{42,3}}; 
    MyClass obj2(a2); 

    // notice obj.data.size() != obj2.data.size() 

    return 0; 
} 

जिसके अनुसार, को बढ़ावा देने :: सरणी अभी भी उपयोगी है (यह इस उदाहरण कोड में भी उपयोगी है), बस नहीं में:

हालांकि, std :: वैक्टर जा रहा है विभिन्न प्रकार के बिना विभिन्न आकारों हो सकता है सटीक तरीका आप इसका उपयोग करना चाहते हैं।

1

आपको त्रुटि के बारे में गलत कर रहे हैं:

template<unsigned long N> MyClass(boost::array<int, N> array) : array(array) {}; 

काम करना चाहिए। वैसे यह संकलन समय पर सरणी उत्पन्न करेगा, इसलिए यह एक अच्छा समाधान नहीं है। और अन्य त्रुटियां घटित होंगी।

यहां आप जो चाहते हैं वह एक वेक्टर है, एक आरक्षित आकार और कुछ दावे जो एक निश्चित आकार पर क्षमता रखते हैं।

+0

उल्लिखित त्रुटि 'boost :: array 'के बारे में है, और वह ऐसा लगता है कि यह सही ढंग से व्याख्या करता है। –

3

नहीं, बूस्ट :: सरणी (यह TR1 में std :: tr1 :: array के रूप में है) एक स्थिर आकार का बफर है। कक्षा का बिंदु एक गतिशील स्मृति आवंटन से बचने के लिए है - आप पूरी तरह से ढेर पर boost :: सरणी डाल सकते हैं।

आप

template<int Size> 
class MyClass 
{ 
private: 
    boost::array<int, Size> m_array; 
public: 
    // .... 
}; 

अपने उदाहरण वर्ग एक टेम्पलेट पूर्णांक लेने के लिए और बढ़ावा :: सरणी सदस्य है कि पारित कर सकते हैं, लेकिन यह सिर्फ ड्रेसिंग है, यह अभी भी एक स्थिर आवंटन है।

+0

ध्यान दें कि यह समाधान समस्या को MyClass श्रेणी में ले जाता है (जहां प्रत्येक टेम्पलेट तत्काल इसका एक अलग प्रकार बन जाएगा)। प्रश्नकर्ता के वास्तविक कार्य के आधार पर यह काम कर सकता है, लेकिन मुझे शक है। – Frunsi

+0

इसके अलावा "यह" आवंटन नहीं है, वाक्यांश भ्रामक है। – Frunsi

+0

यही मेरा मतलब है कि "ड्रेसिंग", और स्थैतिक आकार आवंटन (और स्टैक आवंटन) अभी भी आवंटन हैं। –

5

क्या मैं इसके बजाय boost::scoped_array का उपयोग करने का सुझाव दे सकता हूं? दूसरी ओर, आप वास्तव में प्रति प्रतिलिपि पूरी सरणी नहीं चाहते हैं। फिर boost::shared_array बेहतर विकल्प होगा।

1

हालांकि आप पहले ही एक उत्तर स्वीकार कर चुके हैं, कृपया ध्यान दें कि std :: vector आपके कार्य के लिए सही विकल्प नहीं हो सकता है। यदि आप एक बार सरणी बनाना चाहते हैं - एक निश्चित आकार सरणी - और आप इसे बाद में आकार बदलना नहीं चाहते हैं, तो एक अच्छा पुराना मैदान सरणी आपके लिए सही विकल्प हो सकता है! Boost :: array को अनदेखा करें, std :: vector को अनदेखा करें, इसके इरादे बहुत अलग हैं, इसे सरल रखें। किस, याग्नी और इतने पर ...

int main() { 
    int* array = new int[4]; 
    for(int i=0; i<4; ++i) array[i] = i+1; 
    MyClass obj(array); 
} 

class MyClass { 
    private: 
     int* array; 
    public: 
     MyClass(int* array) 
     : array(array) {} 
     ~MyClass() { delete[] array; } 
}; 

संपादित करें: निकोलाई एन Fetissov जैसा कि पहले ही कहा गया है, को बढ़ावा देने :: scoped_array एक अच्छा विकल्प हो सकता है। यह सरणी के चारों ओर एक पतली RAII wrapper प्रदान करता है। यहां एक उपयोग उदाहरण है (उम्मीद है कि यह सही है, अन्यथा संपादित करने के लिए स्वतंत्र महसूस करें):

class MyClass { 
    private: 
     boost::scoped_array<int> array; 
    public: 
     MyClass(int* array) 
     : array(array) {} 
}; 
+0

हम्म, अनुपलब्ध कॉपी कन्स्ट्रक्टर और कॉपी असाइनमेंट ऑपरेटर यहां। –

+1

बढ़ावा :: सरणी/tr1 :: सरणी एक निश्चित आकार सरणी के चारों ओर एक बहुत ही पतली आवरण है - असल में, इसमें शून्य ओवरहेड है। Tr1 :: सरणी उपलब्ध होने पर सचमुच सी-स्टाइल सरणी का उपयोग करने का कोई कारण नहीं है। –

+1

टेरी: क्या आपने वास्तविक प्रश्न पढ़ा है? अगर आपको प्रश्नकर्ता के इरादे को समझ में नहीं आया तो मुझे नीचे वोट करने का कोई कारण नहीं है। – Frunsi

12

आप कुछ बुनियादी बिंदु खो रहे हैं। आप हो सकता है:

  1. एक स्थिर आवंटित सरणी - char arr[10];
  2. एक गतिशील आवंटित सरणी - char* arr = new arr[10];

पहले एक के आकार संकलन समय के दौरान जाना जाता है (क्योंकि आकार एक है स्थिर), इसलिए आप इसके लिए एक मेमोरी स्पेस को आवंटित कर सकते हैं, दूसरा कोई नहीं है, इसलिए आपको रन-टाइम के दौरान इसके लिए स्मृति आवंटित करने की आवश्यकता है।

एसटीएल/टीआर 1/बूस्ट रैपर दोनों प्रकार के सरणी के लिए प्रदान करता है। वे न केवल विश्वासियों के लिए रैपर हैं, बल्कि सुरक्षा के लिए भी हैं (कुछ स्थितियों में रेंज की जांच) और बिजली (इटरेटर)। दोनों ही मामलों के लिए हम एक अलग आवरण है:

  1. स्थिरता आवंटित सरणी आवरण boost::array<char,10> arr;
  2. गतिशील रूप से आवंटित सरणी आवरण std::vector<char> arr;

उत्तरार्द्ध है स्वयं का आकार बदलने जा रहा है, और आकार बदलने की इजाजत दी, इसके अलावा में के लाभ गतिशील रूप से आवंटित होने के लिए। दूसरी ओर boost::array, type arr[const] निर्माण की नकल करता है।

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

स्थिरता आवंटित टेम्पलेट्स

template < size_t N > 
class MyClass { 
private: 
    boost::array< int, N > array; 
public: 
    MyClass(boost::array< int, N > array) : array(array) {}; 
}; 

// ... 

boost::array<int, 4> array = {{1,2,3,4}}; 
MyClass<4> obj(array); 

का प्रयोग करेंगे लेकिन वर्ग के हर आकार के लिए अलग-अलग कोड बनाना होगा, और वे आपस में प्रचलित (हालांकि इस धोखा दिया जा सकता) नहीं होगा।

गतिशील रूप से प्रयोग करेंगे आवंटित वैक्टर

class MyClass { 
private: 
    std::vector<int> array; 
public: 
    MyClass(const std::vector<int>& array) : array(array) {}; 
}; 

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

0

आप गतिशील आकार बदलने की जरूरत नहीं है, तो आप std :: वेक्टर की जरूरत नहीं है

बस है समारोह * पूर्णांक

MyFunction (int* array,int size); // function prototype 

स्वीकार करते हैं और यह बढ़ावा :: सरणी के पारित डेटा के लिए .डेटा() सूचक ...

boost::array<int,4> testArray; 
boost::array<int,5> testArray2; 

// Calling the function: 
MyFunction(testArray.data(),4); 
MyFunction(testArray2.data(),5); 

कुंजी है .डेटा() लोग !!! यदि आप नियमित सरणी को प्रतिस्थापित करने के लिए एरो को बढ़ावा देना चाहते हैं, तो शायद यह तरीका है (टेम्पलेट्स का उपयोग किए बिना और वह सब कुछ)

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