const char * và char const * - chúng có giống nhau không?


81

Theo hiểu biết của tôi, các constbổ ngữ nên được đọc từ phải sang trái. Từ đó, tôi hiểu rằng:

const char*

là một con trỏ có các phần tử char không thể sửa đổi, nhưng bản thân con trỏ có thể, và

char const*

là một con trỏ liên tục đến các mutableký tự.

Nhưng tôi gặp các lỗi sau cho mã sau:

const char* x = new char[20];
x = new char[30];   //this works, as expected
x[0] = 'a';         //gives an error as expected

char const* y = new char[20];
y = new char[20];   //this works, although the pointer should be const (right?)
y[0] = 'a';         //this doesn't although I expect it to work

Vì vậy, đó là một trong nó? Sự hiểu biết của tôi hoặc trình biên dịch của tôi (VS 2005) có sai không?


35
Khi nghi ngờ luôn sử dụng Quy tắc xoắn ốc .
Alok Save

"... có thể sửa đổi các phần tử char của ai, nhưng bản thân con trỏ có thể, và ..." - Tôi nghĩ bạn muốn nói "không thể" cho một trong những "có thể" đó, nhưng tôi không biết làm thế nào Bạn đang bối rối nên tôi không biết phải sửa cái nào: P
detly 11/11/11

1
Hãy thử trang web này: www.cdecl.org
yasouser

Trình biên dịch không bao giờ sai;)
monolith.

Câu trả lời:


129

Trên thực tế, theo tiêu chuẩn, constsửa đổi phần tử trực tiếp bên trái của nó . Việc sử dụng constở đầu một khai báo chỉ là một lối tắt tinh thần thuận tiện. Vì vậy, hai câu lệnh sau là tương đương:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

Để đảm bảo bản thân con trỏ không bị sửa đổi, constnên đặt sau dấu hoa thị:

char * const constantPointerToMutableContent;

Để bảo vệ cả con trỏ và nội dung mà nó trỏ tới, hãy sử dụng hai khuyết điểm.

char const * const constantPointerToConstantContent;

Cá nhân tôi đã chấp nhận việc luôn đặt hằng số sau phần tôi không định sửa đổi để tôi duy trì tính nhất quán ngay cả khi con trỏ là phần tôi muốn giữ không đổi.


23
'viết tắt tiện lợi' là một mô tả thú vị cho thứ gì đó không ngắn hơn và không tuân theo các quy tắc thông thường.
Beetstra

Tiêu chuẩn không thực sự quan tâm đến thứ tự bạn sử dụng. Phần 7.1.6 chỉ hiển thị cả hai nơi và nói rằng chỉ sử dụng nó trong một.
edA-qa mort-ora-y

1
@beetstra Tôi đồng ý. Tôi đã đổi nó thành "lối tắt tinh thần thuận tiện" để rõ ràng hơn một chút.
Greyson

31

Nó hoạt động vì cả hai đều giống nhau. Có thể bạn nhầm lẫn trong điều này,

const char*  // both are same
char const*

char* const  // unmutable pointer to "char"

const char* const  // unmutable pointer to "const char"

[Để nhớ điều này, đây là một quy tắc đơn giản, '*' ảnh hưởng đến toàn bộ LHS của nó trước tiên ]


Ok, tôi hiểu rồi. Cảm ơn rất nhiều.
Luchian Grigore

1
unmutable pointer to char*. Nó là một con trỏ charkhông thể thay đổi trỏ đến không char *.
Alok Save

25

Đó là bởi vì quy tắc là:

RULE: constliên kết bên trái, trừ khi bên trái không có gì, sau đó liên kết bên phải :)

vì vậy, hãy xem những điều này như:

(const --->> char)*
(char <<--- const)*

Cả hai cùng! oh, và --->><<---KHÔNG nhà khai thác, họ chỉ hiển thị những gì constliên kết với.


2
đúng, toán tử đúng là -->>và nó chỉ hoạt động trên các giá trị. Hãy thử int i = 8; std::cout << (i -->> 1) << std::endl;:)
Alexander Malakhov

11

(từ câu hỏi khởi tạo 2 biến đơn giản )

Một quy tắc ngón tay cái thực sự tốt về const:

Đọc khai báo từ phải sang trái.

(xem Vandevoorde / Josutiss "C ++ Templates: The Complete Guide")

Ví dụ:

int const x; // x is a constant int
const int x; // x is an int which is const

// easy. the rule becomes really useful in the following:
int const * const p; // p is const-pointer to const-int
int const &p;        // p is a reference to const-int
int * const * p;     // p is a pointer to const-pointer to int.

Kể từ khi tôi tuân theo quy tắc ngón tay cái này, tôi không bao giờ hiểu sai những tuyên bố như vậy nữa.

(: sisab retcarahc-rep a no ton, sisab nekot-rep a no tfel-ot-thgir naem I hguohT: tidE


+1 Điều này thật tuyệt vời, cảm ơn bạn! Tôi đã cố gắng tìm hiểu mọi thứ như bao const char* constđời nay và nhờ có bạn mà giờ tôi đã hiểu được điều đó.
OMGtechy,

5

Đây là cách tôi luôn cố gắng giải thích:

char *p

     |_____ start from the asterisk. The above declaration is read as: "content of `p` is a `char`".

char * const p

     |_____ again start from the asterisk. "content of constant (since we have the `const` 
            modifier in the front) `p` is a `char`".

char const *p

           |_____ again start from the asterisk. "content of `p` is a constant `char`".

Hy vọng nó giúp!


0

Trong cả hai trường hợp của bạn, bạn đang trỏ đến một char không đổi.

const char * x  //(1) a variable pointer to a constant char
char const * x  //(2) a variable pointer to a constant char
char * const x  //(3) a constant pointer to a variable char
char const * const x //(4) a constant pointer to a constant char
char const * const * x //(5) a variable pointer to a constant pointer to a constant char
char const * const * const x //(6) can you guess this one?

Theo mặc định, constáp dụng cho những gì ở Ngay bên trái, nhưng nó có thể áp dụng cho những gì Ngay lập tức ở bên phải của nó nếu không có gì trước nó, như trong (1).


Cuối cùng: Một con trỏ biến không đổi, tới một con trỏ không đổi, tới một char hằng.
Secko

Nếu "con trỏ biến không đổi" mà bạn có nghĩa là "con trỏ không đổi", thì bạn đã đóng đinh nó rồi đấy!
Lino Mediavilla

Ở (5) đó là một con trỏ biến đến một con trỏ hằng đến một hằng số char đơn giản vì không có "const" ở bên phải dấu hoa thị cuối cùng trước số nhận dạng "x". Nhưng trong (6) trở thành một con trỏ không đổi, phần còn lại vẫn giữ nguyên.
Lino Mediavilla
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.