Cả chuỗi chữ cũng không s
là con trỏ (họ là mảng), do đó phần có liên quan của tiêu chuẩn là [conv.array]:
Một vế trái hoặc rvalue kiểu "mảng của N
T
" hoặc "mảng liên kết không xác định của T
" có thể được chuyển đổi thành giá trị bằng loại "con trỏ đến T
". Kết quả là một con trỏ đến phần tử đầu tiên của mảng.
Lưu ý rằng
char const *p = s;
f(p);
in "giá trị trái", để chứng minh rằng công trình này như bạn mong đợi cho con trỏ.
Phụ Lục lại: bình luận: Trong trường hợp của
char *p = s;
f(p);
mà in "rvalue" nếu tình trạng quá tải rvalue tồn tại nhưng không gây ra một lỗi biên dịch nếu nó được lấy ra, hai phần khác của tiêu chuẩn đi vào chơi - một trong số đó dường như cấm ràng buộc của char*
đến char const *const &
hoàn toàn và cửa sổ kia mở lại một cửa sổ.
Đầu tiên là [dcl.init.ref]/4, trong đó
loại Với "CV1T1
" và "CV2T2
", "CV1T1
" là tài liệu tham khảo liên quan đến để "CV2T2
" nếu T1
là loại giống như T2
, hoặc T1
là lớp cơ sở của T2
. "CV1T1
" là tham khảo tương thích với "CV2T2
" nếu T1
là tài liệu tham khảo liên quan đến-T2
và CV1 là như nhau cv tuyển như, hoặc cv tuyển lớn hơn, CV2. (...)
Nó tiếp tục theo chiều dài về các quy tắc chính xác để khởi tạo tham chiếu, tất cả đều phù hợp nhưng không may là quá dài đối với câu trả lời SO.Câu chuyện dài được viết ngắn gọn là tham chiếu đến cv1T1
có thể được khởi tạo với đối tượng cv2T2
nếu hai tham chiếu tương thích với tham chiếu.
gì mặt luật pháp, điều này có nghĩa đối với trường hợp của chúng tôi là char*
và char const *
không tham khảo tương thích (mặc dù char*
và char *const
sẽ được), vì char*
không phải là char const *
cũng không phải là một một lớp cơ sở của người kia. Hạn chế này có ý nghĩa nếu bạn xem xét các mảnh trái phép mã sau đó sẽ là hợp pháp khác:
const char c = 'c';
char *pc;
const char*& pcc = pc; // #1: not allowed
pcc = &c;
*pc = 'C'; // #2: modifies a const object
này được chuyển thể từ một ví dụ tương tự trong [conv.qual]/4 có sử dụng một con trỏ đến con trỏ để chứng minh cùng một vấn đề.
[conv.qual] cũng là phần có liên quan khác mà mở cửa sổ trở lại trong Nó nói trong [conv.qual]/1:.
Một prvalue kiểu "con trỏ đến CV1T
"có thể được chuyển đổi sang một prvalue kiểu "con trỏ đến CV2T
" nếu" CV2T
"là hơn cv-có trình độ hơn" CV1T
"
Nó sau từ tất cả điều này mà char*
có thể được chuyển đổi sang char const *
(đó là tài liệu tham khảo tương thích với char const *const
), đó là lý do tại sao mã vẫn biên dịch nếu quá tải rvalue của f
được lấy ra. Tuy nhiên, kết quả của chuyển đổi này là giá trị gia tăng, vì vậy nếu nó có mặt, quá tải rvalue được ưu tiên trong độ phân giải quá tải.
char*
glvalue ->char*
prvalue (bởi [conv.lval]) ->char const *
prvalue)
nên không 'char * p = s; f (p); 'cũng là" lvalue "? Tại sao nó "rvalue"? – alice
Bởi vì một 'char *' không thể bị ràng buộc bởi tham chiếu đến 'char const *' (nó sẽ cho phép bạn phá vỡ const đúng đắn). [conv.qual] áp dụng, lần đầu tiên yêu cầu chuyển đổi từ rvalue sang rvalue và kết quả là các giá trị gia tăng. – Wintermute
Tôi không chắc chắn chính xác const bạn đang đề cập đến. 'Type &' chỉ liên kết với các giá trị có thể sửa đổi, nhưng 'const Type &' liên kết với mọi thứ. Ví dụ, 'string s1 (" abc "); const string & s2 = s1; 'biên dịch tốt. – alice