2009-06-09 67 views
10

Tôi cố gắng để tạo ra một lớp như vậy:Có cách nào để khởi tạo một mảng với các biến không liên tục không? (C++)

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

Tất nhiên, nó không hoạt động cho đến khi tôi thay đổi int x, y; để

const static int x = 10, y = 10; 

Đó là không thực tế, bởi vì tôi đang cố gắng để đọc các giá trị của x và y từ một tệp. Vì vậy, có cách nào để khởi tạo một mảng với các giá trị không contant, hoặc khai báo một mảng và khai báo kích thước của nó trên báo cáo khác nhau? Và tôi biết điều này có lẽ sẽ yêu cầu tạo ra một lớp mảng, nhưng tôi không chắc chắn nơi để bắt đầu này, và tôi không muốn tạo một danh sách động 2D khi mảng chính nó là không năng động, chỉ cần kích thước là không biết tại thời gian biên dịch.

Trả lời

9

Trình biên dịch cần để có kích thước chính xác của lớp khi biên dịch, bạn sẽ phải sử dụng toán tử mới để cấp phát bộ nhớ động.

Chuyển mảng char [x] [y]; thành mảng char **; và khởi tạo mảng của bạn trong hàm tạo và đừng quên xóa mảng của bạn trong trình phá hủ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; 
}; 

* EDIT: Tôi đã có bản sao constructor và toán tử gán

+0

và truy cập một elemtent cụ thể tôi có thể nói mảng [xpos] [ypos] ;? –

+0

Có Keand64, chỉ cần sử dụng mảng [xpos] [ypos]; –

+4

Thật tệ. Còn về xây dựng bản sao. Toán tử gán. Tại sao không có tất cả bộ nhớ trong một khối liền kề hơn là một mảng các mảng. Điều gì về xử lý ngoại lệ trong constructor. –

1

Bạn không thể cấp phát hoặc khởi tạo một mảng toàn cục hoặc tĩnh được khai báo bằng các giá trị không cố định (thời gian biên dịch). Có thể cho các mảng cục bộ mặc dù (các mảng có kích thước biến C99, như initializer của chúng về cơ bản chạy trong thời gian chạy mỗi khi hàm được thực thi).

Đối với tình hình của bạn, tôi khuyên bạn nên sử dụng một con trỏ thay vì một mảng và tạo ra các mảng thực tế năng động trong thời gian chạy (sử dụng 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

vui lòng xây dựng? –

+0

Tôi đã nói về phân bổ và khởi tạo, nói chung. Một mảng có kích thước không được biết là động. Bạn không thể phân bổ bộ nhớ tĩnh một cách kỳ diệu mà không biết số lượng. –

+1

Thật tệ. Còn về xây dựng bản sao. Toán tử gán. Tại sao không có tất cả bộ nhớ trong một khối liền kề hơn là một mảng các mảng. Điều gì về xử lý ngoại lệ trong constructor. –

0

Nếu kích thước không được biết đến tại thời gian biên dịch, mảng là năng động. Những gì bạn có thể làm để giữ cho nó tĩnh là làm cho chúng lớn hơn kích thước mong đợi lớn nhất của bạn.

+0

Điều này sẽ gây ra lỗi biên dịch nếu kích thước đó vượt quá khoảng trống có sẵn trong khung ngăn xếp (thường là 4k). –

+0

Tất nhiên, nhưng anh ta không muốn sử dụng bộ nhớ động? – CookieOfFortune

0

Nếu bạn muốn mảng động có kích thước như một thành viên của lớp, bạn cần mảng new và gán giá trị đó cho con trỏ. Cú pháp char array[size]chỉ cho các mảng có kích thước tĩnh.

Tốt hơn, bạn thực sự nên sử dụng std::vector< std::vector<char> >, có rất ít lý do chính đáng để làm việc theo cách thủ công với mảng có kích thước động trong những ngày này.

15

sử dụng véc tơ.

#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

Tốt như một giải pháp "tiêu chuẩn nghiêm ngặt", nhưng chắc chắn 'boost :: multi_array' cũng đáng được đề cập đến? –

+0

Bạn có thể làm tất cả nội tuyến mà không có vòng lặp: ': x (read_x_from_file()), y (read_y_from_file()), my_array (x, vector (y)) {}'. Điều đó nói rằng, tôi sẽ làm cả việc đọc tệp và phân bổ trong phần thân của ctor. Tôi cố gắng để giữ cho các tác dụng phụ được thực hiện bởi một ctor-initializer đến một số tiền tối thiểu tuyệt đối. –

+0

'sử dụng vector.' làm thế nào là một tùy chọn khi fuction tôi gọi có chữ ký cho một mảng? :/ – n611x007

4

Không theo cách đó, như trong C++, kích thước mảng c-phong cách đã được biết đến tại thời gian biên dịch, với một số phần mở rộng cụ thể nhà cung cấp cho phép kích thước runtime nhất định (để tăng cường khả năng tương thích với C99), nhưng không phải trong tình huống bạn đang mô tả (nếu bạn quan tâm, here's a description). Điều dễ nhất để làm sẽ là:

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

Và áp dụng các kích thước trong constructor:

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

Có rất nhiều ưu điểm của vector trên mảng c phong cách, xem here

2

Đặt tất cả các bộ nhớ vào một khối.
Bởi vì nó là riêng tư, bạn có thể nhận được các phương pháp truy cập của bạn để lấy giá trị chính xác.

nhanh Ví dụ:

#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

Đẹp nhất. Tôi sẽ phải nhớ điều đó. – Luis

1

Bạn có thể cấp phát bộ nhớ cho mảng 2 chiều của mình trong hàm tạo và giải phóng nó trong trình phá hủy. Cách đơn giản nhất:

array = (char **)malloc(sizeof(char *) * x); 
if (array) { 
    for (i = 0; i < x; i++) { 
     array[i] = (char *)malloc(sizeof(char) * y); 
     assert(array[i]); 
    } 
} 
Các vấn đề liên quan