2011-12-05 33 views
25

Tôi có một vector là thành viên trong một lớp và tôi muốn trả lại tham chiếu đến nó thông qua hàm getVector(), để có thể sửa đổi nó sau này. Thực hành tốt hơn hàm getVector() có phải là const không? Tuy nhiên tôi đã nhận được một lỗi "vòng loại giảm trong tham chiếu ràng buộc của loại ..." trong đoạn mã sau. Điều gì cần được sửa đổi?Quay trở lại tham chiếu đến biến số thành viên vector

class VectorHolder 
{ 
public: 
VectorHolder(const std::vector<int>&); 
std::vector<int>& getVector() const; 

private: 
std::vector<int> myVector; 

}; 

std::vector<int> &VectorHolder::getVector() const 
{ 
return myVector; 
} 

Trả lời

27

Vì đây là hàm thành viên const, loại trả về không được tham chiếu không phải là const. Đặt nó const:

const std::vector<int> &VectorHolder::getVector() const 
{ 
    return myVector; 
} 

Bây giờ không sao.

Tại sao nó lại tốt? Bởi vì trong một hàm thành viên const, mỗi thành viên trở thành const theo cách không thể sửa đổi được, có nghĩa là myVector là một vector const trong hàm, đó là lý do tại sao bạn phải trả lại loại const. nó trả về tham chiếu .

Bây giờ, bạn không thể sửa đổi cùng một đối tượng. Xem những gì bạn có thể làm và những gì không thể:

std::vector<int> & a = x.getVector();  //error - at compile time! 

const std::vector<int> & a = x.getVector(); //ok 
a.push_back(10);       //error - at compile time! 

std::vector<int> a = x.getVector();  //ok 
a.push_back(10);       //ok 

Bằng cách này, tôi đang tự hỏi tại sao bạn cần như vậy VectorHolder ở nơi đầu tiên.

+0

Bằng cách này là sau đó không thể thay đổi véc tơ quay trở lại sau đó từ mã nơi bạn quay lại nó? – arjacsoh

+0

@arjacsoh: Điều đó phụ thuộc. Xem chỉnh sửa. – Nawaz

13

nó không phải là bất thường để tuyên bố cả hai biến thể const và có thể thay đổi, như vậy:

std::vector<int>& VectorHolder::getVector() { 
    return myVector; 
} 
const std::vector<int>& VectorHolder::getVector() const { 
    return myVector; 
} 

vấn đề cơ bản với chương trình của bạn là bạn trả về một tham chiếu không const từ một phương pháp const.

std::vector<int>& VectorHolder::getVector() const { 
    return myVector; // << error: return mutable reference from const method 
} 

vì vậy bạn làm cho nó const sử dụng hình thức này:

const std::vector<int>& VectorHolder::getVector() const { 
    return myVector; // << ok 
} 

và khi điều này là trong một phương pháp const không hoặc khách hàng giữ một tham chiếu không const, sau đó bạn có thể sử dụng một cách hợp pháp một phi phương pháp const:

std::vector<int>& VectorHolder::getVector() { 
    return myVector; // << ok 
} 

cuối cùng, bạn có thể trả về giá trị (trong một số trường hợp):

std::vector<int> VectorHolder::getVector() const { 
    return myVector; // << ok 
} 

vì bản sao không yêu cầu đột biến và không cung cấp phơi nhiễm cho dữ liệu nội bộ.

vì vậy bạn sẽ kết thúc tuyên bố cả hai biến thể khá thường xuyên.

kết quả của tuyên bố cả hai đều là:

VectorHolder m; 
const VectorHolder c; 

m.getVector().size(); // << ok 
c.getVector().size(); // << ok - no mutation 

m.getVector().push_back(a); // << ok 
c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned 

vì thế tất cả các công trình ra độc đáo (ngoài những dư thừa của phương pháp).

2

Chức năng getVector có thể được khai báo là const. Nó trả về một tham chiếu có thể được sửa đổi, do đó, trong khi hàm thực tế không sửa đổi bất cứ thứ gì trong lớp, người gọi sẽ có thể sửa đổi dữ liệu nội bộ.

Khai báo nó như là:

std::vector<int>& getVector(); 

Nếu bạn muốn có một hàm trả về một vector mà không thể được sửa đổi, việc sử dụng các const sửa đổi trên cả hai véc tơ và các chức năng:

const std::vector<int>& getVector() const; 
0

Lý do là hàm thành viên const chỉ trả về tham chiếu const. Điều này là do trong một hàm const, mọi thành viên dữ liệu trở thành hằng số.

Vì vậy, bạn phải khai báo các getVector() theo cách này:

std::vector<int> &VectorHolder::getVector() const; 
+2

Bất kể ở trên, có thể không phải là ý tưởng hay khi phơi bày vùng chứa bên trong của bạn. Nếu một ngày nào đó bạn sẽ quyết định chuyển từ véc tơ sang bản đồ, người dùng của bạn sẽ bị ảnh hưởng. Tôi khuyên bạn nên triển khai trình vòng lặp thay thế. – Lev

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