2009-06-09 15 views
10

मैं जैसे एक वर्ग बनाने के लिए कोशिश कर रहा हूँ: क्योंकि मैं कोशिश कर रहा हूँ,गैर-निरंतर चर के साथ सरणी को प्रारंभ करने का कोई तरीका है? (C++)

class CLASS 
{ 
public: 
    //stuff 
private: 
    int x, y; 
    char array[x][y]; 
}; 
बेशक

, यह जब तक मैं

const static int x = 10, y = 10; 

कौन सा अव्यावहारिक है करने के लिए int x, y; बदलने से काम नहीं करता फ़ाइल से एक्स और वाई के मानों को पढ़ने के लिए। तो क्या गैर-contant मूल्यों के साथ एक सरणी शुरू करने का कोई तरीका है, या एक सरणी घोषित करें और विभिन्न आकारों पर इसका आकार घोषित करें? और मुझे पता है कि शायद इसे एक सरणी वर्ग के निर्माण की आवश्यकता होगी, लेकिन मुझे यकीन नहीं है कि इस पर कहां से प्रारंभ करना है, और जब मैं सरणी गतिशील नहीं हूं, तो मैं 2 डी गतिशील सूची नहीं बनाना चाहता, बस आकार है संकलन समय पर ज्ञात नहीं है।

उत्तर

9

संकलक की जरूरत संकलन करते समय कक्षा का सटीक आकार रखने के लिए, आपको गतिशील रूप से स्मृति आवंटित करने के लिए नए ऑपरेटर का उपयोग करना होगा।

स्विच चार सरणी [x] [y]; चार ** सरणी के लिए; और कन्स्ट्रक्टर में अपनी सरणी शुरू करें, और विनाशक में अपनी सरणी को मिटाना न भूलें।

class MyClass 
{ 
public: 
    MyClass() { 
     x = 10; //read from file 
     y = 10; //read from file 
     allocate(x, y); 
    } 

    MyClass(const MyClass& otherClass) { 
     x = otherClass.x; 
     y = otherClass.y; 
     allocate(x, y); 

     // This can be replace by a memcopy 
     for(int i=0 ; i<x ; ++i) 
      for(int j=0 ; j<x ; ++j) 
       array[i][j] = otherClass.array[i][j]; 
    } 

    ~MyClass(){ 
     deleteMe(); 
    } 

    void allocate(int x, int y){ 
     array = new char*[x]; 
     for(int i = 0; i < y; i++) 
      array[i] = new char[y]; 
    } 

    void deleteMe(){ 
     for (int i = 0; i < y; i++) 
      delete[] array[i]; 
     delete[] array; 
    } 

    MyClass& operator= (const MyClass& otherClass) 
    { 
     if(this != &otherClass) 
     { 
      deleteMe(); 
      x = otherClass.x; 
      y = otherClass.y; 
      allocate(x, y); 
      for(int i=0 ; i<x ; ++i) 
       for(int j=0 ; j<y ; ++j) 
        array[i][j] = otherClass.array[i][j];    
     } 
     return *this; 
    } 
private: 
    int x, y; 
    char** array; 
}; 

* संपादित करें: मैं प्रतिलिपि निर्माता और असाइनमेंट ऑपरेटर

+0

और किसी विशेष elemtent तक पहुंचने के लिए मैं सरणी [xpos] [ypos] कह सकता हूं ;? –

+0

हाँ केंड 64, बस सरणी [xpos] [ypos] का उपयोग करें; –

+4

यह बुरा है। कॉपी निर्माण के बारे में क्या। असाइनमेंट ऑपरेटर। सभी स्मृति को सरणी की सरणी के बजाय एक संगत ब्लॉक में क्यों नहीं है। निर्माता में अपवाद हैंडलिंग के बारे में क्या। –

1

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

अपनी स्थिति के लिए, मैं एक सूचक उपयोग करने का सुझाव एक सरणी के बजाय और रनटाइम पर गतिशील वास्तविक सारिणी निर्मित (new उपयोग करते हुए): आकार संकलन समय पर नहीं जाना जाता है

class CLASS 
{ 
public: 
    CLASS(int _x, int _y) : x(_x), y(_y) { 
     array = new char*[x]; 
     for(int i = 0; i < x; ++i) 
      array[i] = new char[y]; 
    } 
    ~CLASS() { 
     for (int i = 0; i < x; ++i) 
      delete[] array[i]; 
     delete[] array; 
    } 
    //stuff 
private: 
    int x, y; 
    char **array; 
}; 
+0

विस्तृत करें कृपया? –

+0

मैं आमतौर पर आवंटन और प्रारंभिकरण के बारे में बात कर रहा था। एक सरणी जिसका आकार ज्ञात नहीं है गतिशील है। आप राशि को जानने के बिना जादुई रूप से स्मृति आवंटित नहीं कर सकते हैं। –

+1

यह बुरा है। कॉपी निर्माण के बारे में क्या। असाइनमेंट ऑपरेटर। सभी स्मृति को सरणी की सरणी के बजाय एक संगत ब्लॉक में क्यों नहीं है। निर्माता में अपवाद हैंडलिंग के बारे में क्या। –

0

हैं, तो सरणी है गतिशील। इसे स्थिर रखने के लिए आप क्या कर सकते हैं उन्हें अपने सबसे बड़े आकार के आकार से बड़ा बनाना है।

+0

जो संकलन त्रुटि का कारण बनता है यदि वह आकार एक स्टैक फ्रेम (आमतौर पर 4k) में उपलब्ध स्थान से अधिक है। –

+0

बेशक, लेकिन वह गतिशील स्मृति का उपयोग नहीं करना चाहता है? – CookieOfFortune

0

यदि आप कक्षा सदस्य के रूप में गतिशील आकार के सरणी चाहते हैं, तो आपको इसे new सरणी करने की आवश्यकता है और उस मान को पॉइंटर को असाइन करना होगा। char array[size] वाक्यविन्यास स्थिर रूप से आकार वाले सरणी के लिए केवल है।

बेहतर अभी तक, आपको वास्तव में std::vector< std::vector<char> > का उपयोग करना चाहिए, इन दिनों गतिशील रूप से आकार वाले सरणी के साथ मैन्युअल रूप से काम करने के बहुत कम अच्छे कारण हैं।

15

वेक्टर का उपयोग करें।

#include <vector> 
class YourClass 
{ 
public: 
    YourClass() 
    : x(read_x_from_file()), y(read_y_from_file()) 
    { 
     my_array.resize(x); 
     for(int ix = 0; ix < x; ++ix) 
      my_array[ix].resize(y); 
    } 

    //stuff 

private: 
    int x, y; 
    std::vector<std::vector<char> > my_array; 
}; 
+1

"कड़ाई से मानक" समाधान के रूप में अच्छा है, लेकिन निश्चित रूप से 'boost :: multi_array' भी उल्लेख का हकदार है? –

+0

आप लूप के बिना सभी इनलाइन कर सकते हैं: ': x (read_x_from_file()), y (read_y_from_file()), my_array (x, वेक्टर (y)) {}'। उस ने कहा, मैं फाइलर पढ़ने और सीटीआर के शरीर में आवंटन दोनों करता हूं। मैं एक सीटीओ-प्रारंभकर्ता द्वारा एक पूर्ण न्यूनतम राशि के दुष्प्रभावों को रखने की कोशिश करता हूं। –

+0

'वेक्टर का उपयोग करें।' यह विकल्प कैसा है जब मैं जिस फक्शन में कॉल करता हूं उसके पास सरणी के लिए हस्ताक्षर होता है? :/ – n611x007

4
कि ढंग से

नहीं, कुछ विक्रेता विशिष्ट निश्चित क्रम आकार (C99 के साथ संगतता को बढ़ाने के लिए) की अनुमति के एक्सटेंशन के साथ संकलन समय पर जाना जाता है जैसा कि C++, सी शैली सरणी आकार दिया है, है, लेकिन में नहीं जिस स्थिति का आप वर्णन कर रहे हैं (यदि आप रुचि रखते हैं, here's a description)। ऐसा करने के लिए सबसे आसान काम होगा:

std::vector< std::vector<char> > array; 

और निर्माता में आकार लागू होते हैं:

array.resize(x); 
for(std::vector< std::vector<char> >::iterator curr(array.begin()),end(array.end());curr!=end;++curr){ 
    curr->resize(y); 
} 

वहाँ सी शैली सरणियों से अधिक वेक्टर के कई लाभ हैं, को देखने के here

2

एक ब्लॉक में सभी स्मृति रखो लिया है।
क्योंकि यह निजी है, तो आप सही मूल्य प्राप्त करने के लिए अपनी पहुंच विधियां प्राप्त कर सकते हैं।

त्वरित उदाहरण:

#include <vector> 
#include <iostream> 

class Matrix 
{ 
    public: 
    class Row 
    { 
     public: 
     Row(Matrix& p,unsigned int x) 
      :parent(p) 
      ,xAxis(x) 
     {} 
     char& operator[](int yAxis) 
     { 
      return parent.data(xAxis,yAxis); 
     } 
     private: 
      Matrix&   parent; 
      unsigned int xAxis; 
    }; 

    Matrix(unsigned int x,unsigned int y) 
     :xSize(x) 
     ,ySize(y) 
     ,dataArray(x*y) 
    {} 

    Matrix::Row operator[](unsigned int xAxis) 
    { 
     return Row(*this,xAxis); 
    } 
    char& data(unsigned int xAxis,unsigned int yAxis) 
    { 
     return dataArray[yAxis*xSize + xAxis]; 
    } 
    private: 
     unsigned int xSize; 
     unsigned int ySize; 
     std::vector<char> dataArray; 
}; 


int main() 
{ 
    Matrix  two(2,2); 

    two[0][0] = '1'; 
    two[0][1] = '2'; 
    two[1][0] = '3'; 
    two[1][1] = '4'; 

    std::cout << two[1][0] << "\n"; 
    std::cout << two.data(1,0) << "\n"; 
} 
+0

बहुत कम कर सकता है। मुझे उस चाल को याद रखना होगा। – Luis

1

आप कन्स्ट्रक्टर में अपनी 2-आयामी सरणी में स्मृति आवंटित कर सकते हैं और इसे विनाशक में मुक्त कर सकते हैं। सबसे आसान तरीका:

array = (char **)malloc(sizeof(char *) * x); 
if (array) { 
    for (i = 0; i < x; i++) { 
     array[i] = (char *)malloc(sizeof(char) * y); 
     assert(array[i]); 
    } 
} 
संबंधित मुद्दे