2017-09-08 32 views
29

Tôi không chắc chắn ý nghĩa thực sự của const vector<int *> vì vậy tôi đã biên dịch mã dưới đây để có được một ý tưởng nhưng bây giờ là bối rối hơn.Tại sao yếu tố không tham chiếu trong vector const của con trỏ int có thể thay đổi được?

vector<int *> v; 
int x = 1, y = 2; 
v.push_back(&x); 
v.push_back(&y); 

const vector<int *> w = v; 
w[0] = &y; //failed. Element is a constant pointer? 
*(w[0]) ++; //failed. Element pointer references to constant value? 

Nếu tôi đã dừng lại ở đây, tôi sẽ giả định rằng const vector<int *> là một vector của const int * const, nhưng sau đó tôi đã cố gắng sau đó mâu thuẫn với giả định rằng rõ ràng.

*(w[0]) += 3; //passed. Value not constant? 
*(w[0]) = 20; //passed. Why... 

Bây giờ *(w[0]) vì lý do lạ lẫm với tôi rõ ràng là đối xử với +++= và phân công khác nhau. Tôi tự thuyết phục rằng const vector chỉ khai báo một đối tượng không đổi của lớp vector và kết quả trên có thể phụ thuộc vào việc thực hiện quá tải thực tế của lớp vector. Nhưng tôi không thể quấn quanh đầu. Bất cứ ai có thể giúp giải thích, xin vui lòng?

Nếu nó có liên quan, tôi đã sử dụng g ++ 4.2 trên máy Mac.

+1

Bạn có thể thấy điều này thú vị: Thay đổi bài đăng thành tiền gia tăng và xem điều gì xảy ra trên ví dụ về lỗi thứ hai. '++ * (w [0]);'. – WhozCraig

+1

Tôi nghĩ rằng một nguồn lớn của sự nhầm lẫn là viết '* (w [0]) ++;' thay vì '(* w [0]) ++;' (mà tôi nghĩ là có khả năng là kết quả dự định). Ưu tiên của nhà điều hành có thể đôi khi hơi phức tạp. – Kat

Trả lời

33

Tại sao yếu tố không tham chiếu trong vector const của con trỏ int có thể thay đổi?

Đối const vector<int *>, nguyên tố này sẽ là const con trỏ đến phi const, ví dụ: int * const, vì vậy bạn có thể chỉnh sửa các đối tượng được trỏ bởi con trỏ, nhưng không phải là con trỏ chính nó.

Theo Operator Precedence, nhà điều hành tăng postfix có độ ưu tiên cao hơn operator*, vì vậy *(w[0]) ++; tương đương với

* ((w[0]) ++); 

Các increment trên con trỏ được thực hiện lúc đầu, sau đó nó bị lỗi. w[0] = &y; cũng đang cố gắng sửa đổi con trỏ, vì vậy nó cũng không thành công.

Mặt khác, (*w[0]) ++; (tức là tăng trên điểm được chọn) sẽ không sao. Và các câu lệnh sau cũng tốt, bởi vì cả hai đều sửa đổi các đối tượng được trỏ bởi con trỏ chứ không phải con trỏ.

*(w[0]) += 3; //passed. 
*(w[0]) = 20; //passed. 
9

Đó là vấn đề của operator precedence.

Khi bạn thực hiện *(w[0]) ++ bạn cố gắng sửa đổi con trỏ .

Khi bạn thực hiện *(w[0]) += 3 bạn sửa đổi dữ liệu được trỏ tới bởi con trỏ.

5

wconst vector<int *>. Bộ mã số const được áp dụng cho vectơ. Do đó, tương ứng với chức năng const thành viên sẽ được sử dụng cho các operator[]:

const_reference operator[](size_type pos) const;

Kể từ khi vector là const -qualified và chứa các yếu tố của loại int * (và không const int *), kiểu của biểu thức w[0]int * const& (thay vì const int *&).Đó là, đó là một tài liệu tham khảo đến một con trỏ hằng đến một int và không phải là một tài liệu tham khảo đến một con trỏ đến một hằng số int: các constness được áp dụng cho con trỏ chính nó, không để các dữ liệu được chỉ.

Bằng cách *(w[0]) += 3 bạn không thay đổi giá trị của con trỏ vector trả (đó là const), nhưng giá trị con trỏ này trỏ đến. Vì con trỏ này thuộc loại int * const (và không phải là const int *), bạn có thể sửa đổi những gì nó trỏ đến, vì vậy nó hoạt động. Tuy nhiên, làm w[0] = &y đang thực hiện một nhiệm vụ trên một con trỏ không đổi, do đó, nó không biên dịch.

0

const vector<T> cho phép bạn truy cập các phần tử của nó là T const & (tức làconst T &). Trong trường hợp này, Tint *, vì vậy đây là int * const &, tham chiếu const tới con trỏ trỏ đến int. Con trỏ là hằng số, nhưng int thì không.

Các loại vector sẽ cần thiết để được vector<int const *> (ví dụvector<const int*>) trong trường hợp đó các phần tử sẽ được truy cập thông qua int const * const &.

Dòng dưới cùng, constness là transitive với các mẫu chứ không phải với con trỏ. Và nếu bạn đặt con trỏ trong các mẫu, bạn sẽ có được một chút về cả hai hành vi.

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