2014-10-28 6 views
6

मैं गतिशील सरणी (कुछ std :: vector की तरह) के लिए कुछ कक्षाओं को डिजाइन करने की प्रक्रिया में हूं। कारण मैं std :: वेक्टर का उपयोग नहीं करना चाहता क्योंकि मेरा सी ++ प्रोग्राम अक्सर सी/सी ++/फोरट्रान/डेल्फी नामक लाइब्रेरी के रूप में उपयोग किया जाता है और इसलिए पॉइंटर के रूप में सरणी इनपुट लेता है। सुरक्षा कारणों से, एक std :: वेक्टर निर्माण समय पर एक सूचक को चुरा नहीं सकता है। मेरा Array1D एक std :: वेक्टर के रूप में काम कर सकता है लेकिन एक सूचक के साथ भी बनाया जा सकता है। दुर्भाग्यवश विजुअल स्टूडियो 2013 मेरे डिजाइन के बारे में चिंतित है। समस्या पेश करने से पहले, मुझे इस डिजाइन को समझाने की जरूरत है।सी ++ गतिशील सरणी का डिजाइन

यहाँ, मेरी कक्षा

template <typename T> 
class Array1D { 
private: 
    T* data_; 
    T* size_; // No stored as an int for optimisation purposes 
    bool owner_; 
public: 
    Array1D(int n) { 
     data_ = new T[n]; 
     size_ = data_ + n; 
     owner_ = true; 
    } 
    Array1D(T* data, int n) { 
     data_ = data; 
     size_ = data + n; 
     owner_ = false; 
    } 
    ... 
}; 

अधिकांश समय के लेआउट है यह एक std :: वेक्टर के रूप में काम करता है और owner_ सही पर सेट किया जाता है। कोई भी पॉइंटर से Array1D भी बना सकता है, और इस बार owner_ को गलत पर सेट किया गया है। इस मामले में, कुछ संचालन जैसे आकार बदलने की अनुमति नहीं है (एक जोर के माध्यम से)। कॉपी निर्माता और सरणी एक के लिए काम तैयार कर रहे हैं के रूप में:

  • Array1D (स्थिरांक & बी Array1D): बी के डीप कॉपी ए निर्माण के बाद में, एक अपनी स्मृति का मालिक है।
  • ऐरे 1 डी (ऐरे 1 डी & & बी): सभी मामलों में ऑपरेशन ले जाएं। निर्माण के बाद, ए की स्वामित्व स्थिति बी
  • ऑपरेटर = (कॉन्स एरे 1 डी & बी): बी में ए की गहरी प्रतिलिपि अगर ए के पास इसकी स्मृति नहीं है, तो ए और यह जांचने के लिए एक जोर है बी एक ही आकार है। असाइनमेंट ए
  • ऑपरेटर = (Array1D & & बी) की स्वामित्व स्थिति को नहीं बदलेगा: यदि ए और बी उनकी याददाश्त का मालिक है तो ऑपरेशन ले जाएं। अन्यथा, हम एक गहरी प्रतिलिपि करते हैं, और यदि आकार की स्मृति नहीं है तो आकार को एक assert के साथ चेक किया जाता है। असाइनमेंट ए के स्वामित्व की स्थिति

मैं अपने 2 आयामी सरणी जिसका तत्वों में रो-प्रमुख आदेश

template <typename T> 
class Array2D { 
private: 
    T* data_; 
    T* size_[2]; 
    bool owner_; 
public: 
    Array2D(int n, int p) { 
     data_ = new T[n]; 
     size_[0] = data_ + n; 
     size_[1] = data_ + p; 
     owner_ = true; 
    } 
    Array1D(T* data, int n, int p) { 
     data_ = data; 
     size_[0] = data + n; 
     size_[1] = data + p; 
     owner_ = false; 
    } 
    ... 
    Array1D<T> operator()(int i) { 
     Array1D<T> row(data_ + i * nb_columns(), nb_columns()); 
     return row; 
    } 
    ... 
    int nb_columns() const { 
     return static_cast<int>(size_[1] - data_); 
    } 
}; 

Array1D ऑपरेटर द्वारा वापस जमा हो जाती है के लिए एक ही विचार आवेदन किया है परिवर्तन नहीं करता है () (int i) में इसकी स्मृति नहीं है और इसमें Array2D ऑब्जेक्ट के स्वामित्व वाली ith-row में पॉइंटर शामिल है। है कोड

sort(Array1D<T>& A); // A function that sorts array in place 

Array2D<double> matrix(5, 100); // Construct an array of 5 rows and 100 columns 
...        // Fill the array 
sort(matrix(3))     // Sort the 4th row 

के निम्नलिखित प्रकार में उपयोगी है एक 2 आयामी सरणियों की पंक्तियों के लिए उन "अस्थायी दृश्य" काफी उपयोगी होते हैं, लेकिन मैं अलियासिंग सीमित करने के लिए अस्थायी वस्तुओं के लिए उन्हें सीमित करने के लिए पसंद करते हैं।

दुर्भाग्य से, विजुअल स्टूडियो 2013 का उपयोग करके, मुझे लाइन सॉर्ट (मैट्रिक्स (3)) के लिए आईडीई से निम्नलिखित चेतावनी मिलती है: "एल-वैल्यू संदर्भ में आर-वैल्यू बाध्य करने के विकल्प गैर मानक माइक्रोसॉफ्ट सी ++ एक्सटेंशन है" । मैं समझता हूं कि मैट्रिक्स (3) एक ऐसी वस्तु है जो अस्थायी रूप से रहती है और इसे एक तरह से संशोधित करती है अजीब लगती है। लेकिन, जैसा कि यह एक "दृश्य" है, इसे संशोधित करना मैट्रिक्स के स्वामित्व वाली स्मृति को संशोधित करता है और उपयोगी है।

तो मेरे सवालों का अनुसरण कर रहे हैं:

  • मैं वैध सी क्या कर रहा हूँ है ++? (अस्थायी मान को संशोधित करना)
  • क्या इस डिज़ाइन में कोई दोष है?

पीएस: पूरा कोड Github पर उपलब्ध है।

+0

आपके द्वारा दिए गए 'सॉर्ट' का प्रोटोटाइप एक मान प्रकार लेता है, न कि एक lvalue संदर्भ प्रकार। – ecatmur

+0

आपका 'Array1D ऑपरेटर() (int i) कैसे है; लागू किया गया? – Ashalynd

+0

@ecatmut: आपकी टिप्पणियों के लिए धन्यवाद। पोस्ट संपादित किया गया है। – InsideLoop

उत्तर

0

क्या मैं वैध सी ++ कर रहा हूं? (अस्थायी मान को संशोधित करना)

ऐसा नहीं है। गैर-स्थिरांक lvalue संदर्भ अस्थायी वस्तुओं के लिए बाध्य नहीं कर सकते हैं: http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

वहाँ इस डिजाइन में एक दोष है?

आप किसी ऑब्जेक्ट में लिपटे सामग्रियों को संशोधित कर रहे हैं। चूंकि आप एक lvalue की आवश्यकता है, यह बस एक मध्यवर्ती चर होने से निर्धारित किया जाएगा:

auto m_temp_lvalue = matrix(3); // get the 4th row 
sort(m_temp_lvalue); // sort the 4th row 

मुझे आशा है कि यह मदद करता है।

+0

आपके स्पष्टीकरण के लिए धन्यवाद। भले ही आपका इंटरमीडिएट वैरिएबल विचार काम करता है, फिर भी मैंने अंततः उन "विचारों" से बचने का फैसला किया और स्मृति में कुछ स्थान पर इंगित करने वाला केवल एक Array1D है। यह चीजों को सुरक्षित बनाता है। – InsideLoop

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