2010-09-15 62 views
19

Làm cách nào để trả về mảng đa chiều ẩn trong trường riêng?C++ Trả về mảng đa chiều từ hàm

class Myclass { 
private: 
int myarray[5][5]; 
public: 
int **get_array(); 
}; 

........ 

int **Myclass::get_array() { 
return myarray; 
} 

có thể không chuyển đổi int (*)[5][5]-int** lại test.cpp/Polky/src dòng 73 C/C++ Vấn đề

+4

lưới là gì? không phải là 'myarray'? – woodstok

+3

Trả lại tài liệu tham khảo trực tiếp cho thành viên riêng tư có thể không phải lúc nào cũng là ý tưởng hay - bạn có thể đóng gói hiệu quả bằng cách này, cho phép mọi người truy cập và sửa đổi thành viên riêng tư của bạn. Điều này có thể hoặc có thể không được chấp nhận trong thiết kế của bạn. –

+0

@MIkhail: Vì justin chưa trực tuyến kể từ phút anh ấy đăng câu hỏi này, tôi đã tự do sửa nó. – sbi

Trả lời

-1

Thay đổi của int của bạn để int [] [] 's hoặc thử sử dụng int [,] thay vì ?

+1

'int [,]' không hợp lệ C++ –

+3

... và 'int [] []' cũng không hợp lệ. Trong trường hợp này, điều quan trọng là phải hiểu sự khác nhau giữa các mảng và con trỏ. – visitor

+2

@David: Trên thực tế, 'new int [5, 5]' là hợp lệ C++, nó chỉ không làm những gì người ta có thể nghĩ - nó giống như 'new int [5]' nhờ toán tử dấu phẩy :) – fredoverflow

-1
int **Myclass::get_array() { 
return (int**)myarray; 
} 
+1

xấu của tôi Nếu bạn sử dụng nó, bạn sẽ diễn giải lại các phần tử của mảng như con trỏ. –

+0

@Mike Seymour, và đó là sự thật nếu bạn xem xét mỗi hàng là int * (giống như mỗi vectơ của số nguyên int *). – rkellerm

4

Để trả về một con trỏ đến mảng của bạn của thành viên mảng, loại cần thiết là int (*)[5], không int **:

class Myclass { 
private: 
    int myarray[5][5]; 
public: 
    int (*get_array())[5]; 
}; 

int (*Myclass::get_array())[5] { 
    return myarray; 
} 
1

tôi quản lý để làm cho công việc chức năng này trong C++ 0x sử dụng khấu trừ loại tự động . Tuy nhiên, tôi không thể làm cho nó hoạt động mà không có điều đó. Các mảng C bản địa không được hỗ trợ rất tốt trong C++ - cú pháp của chúng cực kỳ ghê gớm. Bạn nên sử dụng một lớp bao bọc.

template<typename T, int firstdim, int seconddim> class TwoDimensionalArray { 
    T data[firstdim][seconddim]; 
public: 
    T*& operator[](int index) { 
     return data[index]; 
    } 
    const T*& operator[](int index) const { 
     return data[index]; 
    } 
}; 
class Myclass { 
public: 
    typedef TwoDimensionalArray<int, 5, 5> arraytype; 
private: 
    arraytype myarray; 
public: 
    arraytype& get_array() { 
     return myarray; 
    } 
}; 

int main(int argc, char **argv) { 
    Myclass m; 
    Myclass::arraytype& var = m.get_array(); 
    int& someint = var[0][0]; 
} 

Mã này chỉ biên dịch tốt. Bạn có thể nhận được lớp bọc trước bằng văn bản bên trong Boost (boost :: array) hỗ trợ toàn bộ shebang.

+0

Không biên dịch với GCC: dữ liệu trả về đầu tiên [index] tạo một tham chiếu không const từ một giá trị, nó nói. – Cubbi

+0

Và đó là trường hợp, một con trỏ trần nên được trả lại, không phải là một tham chiếu đến một con trỏ. Nếu không, chúng tôi có ít nhất đạt được nhiều trong khả năng đọc. Một điểm nhỏ: tại sao sử dụng 'int' cho các kiểu mẫu thực tế? Một cái gì đó mà không thể có thể là tiêu cực sẽ được thể hiện tốt hơn với một loại số nguyên unsigned tôi nghĩ. –

+0

dữ liệu [chỉ mục] là một lvalue, không phải là một rvalue, giống như * ptr là một lvalue. Không phải là tài liệu tham khảo là thực sự cần thiết, tôi nghĩ rằng đó là từ một phiên bản trước của mã, bạn có thể có thể loại bỏ nó. – Puppy

22

Mảng hai chiều không phân rã thành con trỏ thành con trỏ thành int. Nó phân rã thành một con trỏ tới các mảng ints - tức là chỉ có chiều thứ nhất phân rã thành một con trỏ. Con trỏ không trỏ đến con trỏ int, mà khi tăng lên trước bởi kích thước của một con trỏ, nhưng để mảng của 5 số nguyên.

class Myclass { 
private: 
    int myarray[5][5]; 
public: 
    typedef int (*pointer_to_arrays)[5]; //typedefs can make things more readable with such awkward types 

    pointer_to_arrays get_array() {return myarray;} 
}; 

int main() 
{ 
    Myclass o; 
    int (*a)[5] = o.get_array(); 
    //or 
    Myclass::pointer_to_arrays b = o.get_array(); 
} 

Một con trỏ đến con trỏ (int**) được sử dụng khi mỗi mảng con được phân bổ riêng biệt (có nghĩa là, bạn ban đầu có một mảng các con trỏ)

int* p[5]; 
for (int i = 0; i != 5; ++i) { 
    p[i] = new int[5]; 
} 

Ở đây chúng ta có một mảng trong số năm con trỏ, mỗi trỏ đến mục đầu tiên trong một khối bộ nhớ riêng biệt, hoàn toàn 6 khối bộ nhớ riêng biệt.

Trong một mảng hai chiều bạn sẽ có được một khối liền kề duy nhất của bộ nhớ:

int arr[5][5]; //a single block of 5 * 5 * sizeof(int) bytes 

Bạn sẽ thấy rằng việc bố trí bộ nhớ của những điều này là hoàn toàn khác nhau, và do đó những điều này không thể được trả lại và vượt qua cùng một cách.

+0

+1 cảm ơn, câu trả lời tuyệt vời –

2

Làm cách nào để trả lại mảng đa chiều ẩn trong trường riêng tư?

Nếu nó được cho là bị ẩn, tại sao bạn trả lại nó ngay từ đầu?

Dù sao, bạn không thể trả về mảng từ hàm, nhưng bạn có thể trả về con trỏ đến phần tử đầu tiên. Yếu tố đầu tiên của một mảng 5x5 của int là gì? Một mảng của 5 ints, tất nhiên:

int (*get_grid())[5] 
{ 
    return grid; 
} 

Ngoài ra, bạn có thể trả lại toàn bộ mảng bằng cách tham khảo:

int (&get_grid())[5][5] 
{ 
    return grid; 
} 

...chào mừng bạn đến với địa chỉ cú pháp khai báo C ;-)

Tôi có thể đề xuất std::vector<std::vector<int> > hoặc boost::multi_array<int, 2> để thay thế?

16

Có hai loại có thể bạn có thể quay lại để cung cấp quyền truy cập vào mảng nội bộ của mình. Kiểu C cũ sẽ trả về int *[5], vì mảng sẽ dễ dàng phân rã thành con trỏ thành phần tử đầu tiên, thuộc loại int[5].

int (*foo())[5] { 
    static int array[5][5] = {}; 
    return array; 
} 

Bây giờ, bạn cũng có thể trả về một tài liệu tham khảo thích hợp để các mảng nội bộ, cú pháp đơn giản nhất sẽ được thông qua một typedef:

typedef int (&array5x5)[5][5]; 
array5x5 foo() { 
    static int array[5][5] = {}; 
    return array; 
} 

Hoặc một chút cồng kềnh hơn mà không typedef:

int (&foo())[5][5] { 
    static int array[5][5] = {}; 
    return array; 
} 

Ưu điểm của phiên bản C++ là loại thực tế được duy trì và điều đó có nghĩa là kích thước thực của mảng được biết ở phía người gọi.

+0

+1 cho phiên bản C++ (với typedef thích hợp) –

+1

Mặc dù hãy cẩn thận cách bạn sử dụng các typedef đó, đôi khi: 'delete [] new array5x5()' (trông mới, nhưng nó thực sự mới []). –