2017-06-17 27 views
11

Điều này hoạt động rất tốt ...Tại sao không tham chiếu đến một mảng hoạt động cho đến khi chúng ta sử dụng một con trỏ?

int a[5] = {1,2,3,4,5}, int *p = a; 
int *& ref = p; 

Nhưng tại sao tính năng này không hoạt động?

int a[5] = {1,2,3,4,5}; 
int*& ref = a; 

Cả ap là con trỏ và có giá trị như nhau (địa chỉ của a[0]). Khi tôi tham chiếu đến một mảng bằng cách sử dụng con trỏ (p), nó hoạt động rất tốt.

Nhưng khi tôi tham chiếu đến mảng đó a[] trực tiếp, nó không hoạt động ... Tại sao?

Trả lời

25

a không phải là con trỏ, nó là một mảng. Nó có loại int[5]. Những gì nó có thể làm là phân rã thành một con trỏ int*, đó là những gì xảy ra trong trường hợp đầu tiên. Vì vậy, tham chiếu đến p là ok.

Bây giờ cho trường hợp thứ hai. Hãy nhớ rằng akhông phải là một con trỏ. Vì vậy, có một chuyển đổi tiềm ẩn xảy ra từ int[5] đến int*. Kết quả của chuyển đổi đó là giá trị gia tăng. Nhưng bạn không thể ràng buộc một tham chiếu không phải l constue (đó là những gì ref là) để một rvalue! Vì vậy, mã không biên dịch được.

Dưới đây là một loại suy:

double a = 1.4; 
int& b = a; // implicit conversion from 'double' to `int` results in prvalue 
      // and you can't bind non-const lvalue refs to rvalues. 
0
int*& ref = a; 

int* là một loại con trỏ, không phải là một kiểu mảng. Vì vậy, đó là lý do tại sao nó sẽ không liên kết với a, có loại int[5].

Vì vậy, sử dụng const

int* const& ref = a; 

Đó là hoạt động tốt, Bởi vì tên mảng là một địa chỉ cố định, tài liệu tham khảo không const không có thể tham khảo một hằng số.

+5

Tên mảng không phải là một "địa chỉ liên tục". Điều này làm việc vì một tham chiếu const có thể bị ràng buộc vào tạm thời mà các mảng phân rã tạo ra. – Quentin

+0

Địa chỉ của * tĩnh * mảng là một hằng số địa chỉ. Địa chỉ của * local * array không. – AnT

9

Thêm vào những gì đã được trả lời, bạn có thể nhận được một tham chiếu đến một mảng như

int a[5]; 
int (&ref)[5] = a; 

Live

+0

Tôi vừa mới thêm cái này (nhưng phải kiểm tra lỗi cú pháp trước đó). Do đó, tôi có thể thêm ít nhất: 'g ++ -std = C++ 11' đã chấp nhận điều này. (Nhưng tôi nhớ rằng tôi cũng đã sử dụng nó trong VS2013 trong quá khứ.) – Scheff

+4

@Scheff Điều này cần C++ mới hơn? Có thật không? Tôi nghĩ đây là cú pháp cổ. [Có vẻ ổn với tôi] (https://godbolt.org/g/vsCiBz) –

+0

Bạn hoàn toàn đúng. Tôi chỉ mô tả những gì tôi vừa thử nghiệm (không phải những gì tôi chắc chắn sẽ biết). (Có thể là, tuổi của tôi đã để tôi trở nên quá cẩn thận ...) – Scheff

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