2012-04-10 25 views
11

Tôi khá mới đối với C++ nên đây có thể là một câu hỏi tầm thường:Làm cách nào để trả về đúng mảng (thành viên lớp) trong C++?

Lớp của tôi có biến thành viên riêng là một mảng. Tôi cần phải trả lại mảng đó, nhưng tôi không chắc chắn làm thế nào để làm điều đó đúng.

class X { 
    // ... 
    private: double m_Array[9]; 
    public: double* GetArray() const { return m_Array; } 
}; 

Có vấn đề gì với mã này không? Điều này trả về một con trỏ đến thành viên lớp, phải không? - vì vậy nếu tôi lấy mảng đó từ một thể hiện của lớp này và sửa đổi nó (từ bên ngoài lớp), mảng thành viên lớp ban đầu cũng sẽ bị thay đổi? Nếu đúng như vậy, làm cách nào để tôi trả lại bản sao của mảng đó?

+2

xem xét 'std :: vector < double >' nếu kích thước mảng không cố định (trong ví dụ của bạn có vẻ như cố định, vì vậy đừng lo lắng). Thêm lợi ích: bạn có thể trả về một tham chiếu đến vectơ. – hochl

+2

Thông thường với các đối tượng bạn đóng gói dữ liệu và hành vi. Có một lý do 'X' không thể làm những gì bạn muốn? [Nói, đừng hỏi] (http://pragprog.com/articles/tell-dont-ask). –

Trả lời

10

Điều này trả về con trỏ cho thành viên lớp học, phải không?

Gần như - nó trả về con trỏ đến phần tử đầu tiên của mảng.

nếu tôi tìm nạp mảng đó từ một thể hiện của lớp này và sửa đổi nó (từ bên ngoài lớp), mảng thành viên lớp ban đầu cũng sẽ được thay đổi?

Đúng vậy.

Nếu đúng như vậy, làm cách nào để trả lại bản sao của mảng đó?

Cách dễ nhất để đạt được điều đó là sử dụng std::array hoặc std::vector thay thế. Bạn nên trả lại tham chiếu const cho nó - sau đó người gọi tránh chi phí sao chép khi không cần thiết. Ví dụ:

class X { 
    std::array<double, 9> array; 
public: 
    std::array<double, 9> const & GetArray() const {return array;} 
}; 

X x; 
double d = x.GetArray()[5]; // read-only access, no copy 

auto array = x.GetArray(); // get a copy 
array[5] = 42;    // modify the copy 

Ngoài ra, nếu mảng có kích thước cố định (như trong ví dụ của bạn), bạn có thể trả về một mảng chứa trong một cấu trúc - đó là std::array là gì. Nếu không, bạn có thể trả lại một con trỏ (tốt hơn là một con trỏ thông minh, để tránh rò rỉ bộ nhớ) cho một mảng mới được phân bổ - đó là nhiều hơn hoặc ít hơn những gì std::vector là.

+0

Có, bạn sẽ phải 'sao chép' nó, hoặc trong trường hợp của một mảng, sao chép nội dung vào một mảng mới. –

+0

+1, nhưng không phải là tốt hơn để tạo ra somekind của 'mảng xem' thay vào đó một struct được trả về mà thực hiện operator [], như tôi sẽ giả định rằng sao chép mảng sẽ sử dụng rất nhiều bộ nhớ và thời gian –

+0

@YetAnotherGeek: hỏi cách trả về một bản sao của mảng, vì vậy nó có thể được sửa đổi mà không ảnh hưởng đến bản gốc. Bạn không thể làm điều đó mà không cần sao chép nó. –

2

Để trả lại bản sao, new mảng double cần phân bổ động, điền với giá trị hiện tại là m_Array và được trả lại cho người gọi (con trỏ đến phần tử đầu tiên cụ thể). Người gọi sẽ chịu trách nhiệm delete[] ing mảng được trả về. Khi nó đứng, người gọi không có kiến ​​thức về số lượng các phần tử trong mảng được trả về.

Vì đây là C++, thay vào đó hãy thay đổi thành số std::vector<double>: điều này sẽ xử lý việc sao chép cho bạn và cung cấp cho người gọi thông tin về số lượng double s.

2

Có, khi bạn thay đổi mảng, bạn cũng sẽ thay đổi thành viên của lớp.

Tôi khuyên bạn nên sử dụng std :: vector thay vì mảng kiểu c trong C++. Nó sẽ làm cho cuộc sống của bạn dễ dàng hơn và sẽ làm cho mã dễ đọc hơn. Nếu vẫn còn một lý do để bạn nhấn mạnh vào việc sử dụng mảng, bạn cần phải cấp phát một mảng mới và trả về một con trỏ tới nó.Lưu ý rằng điều này sẽ buộc bạn phải xử lý bộ nhớ động và cẩn thận giải phóng bộ nhớ động:

public: 
    double* GetArray() { 
    double* res = new double[9]; 
    for (int i = 0; i < 9; ++i) { 
     res[i] = m_Array[i]; 
    } 
    return res; 
    } 

Bạn cũng có thể sử dụng memcpy để sao chép các phần tử của mảng.

Các vấn đề liên quan