2010-01-27 52 views
8

Các dòng mã sau đây biên dịch tốt và hoạt động:typedef và container của con trỏ const

list<const int *> int_pointers; // (1) 

Hai dòng sau đây không:

typedef int * IntPtr; 
list<const IntPtr> int_pointers; // (2) 

tôi nhận được chính xác cùng một biên dịch lỗi cho

list<int * const> int_pointers; // (3) 

Tôi biết rằng dòng cuối cùng không hợp pháp vì các thành phần của vùng chứa STL cần phải là có thể gán. Tại sao trình biên dịch giải thích (2) lại giống như (3)?

Trả lời

9

Câu trả lời ngắn:

  1. là danh sách các con trỏ để ints không đổi.
  2. là danh sách các con trỏ liên tục đến int.
  3. giống như 2.

const (và dễ bay hơi) sẽ tự nhiên xuất hiện sau loại chúng đủ điều kiện. Khi bạn viết nó trước, trình biên dịch sẽ tự động ghi đè nó trong nội bộ:

const int * 

trở thành

int const * 

mà là một con trỏ đến một int không đổi. Danh sách này sẽ biên dịch tốt vì con trỏ chính nó vẫn có thể gán được.

8

Bạn đọc các khai báo kiểu kiểu C từ phải sang trái. Vì vậy, "const int *" là một con trỏ đến ints liên tục ("const int" và "int const" có nghĩa là cùng một điều). Những điều đó hoàn toàn có thể chuyển nhượng được. Nhưng (2) và (3) là các con trỏ liên tục đến int, và do đó không thể gán được.

5

const IntPtrconst int* không giống nhau.

1) const int* là "con trỏ đến const int".

2) const IntPtr mở rộng để int * const (nghĩ (int *) const) mà là "const con trỏ đến int".

Tóm lại, typedef hoạt động như một tập hợp các dấu ngoặc đơn. Bạn không thể thay đổi số const -ness của con trỏ trỏ đến.

3

const int * cũng giống như viết int const *, có nghĩa là giá trị không đổi được trỏ bởi một con trỏ không liên tục.

Với typedef bạn xác định con trỏ là hằng số, như trong câu lệnh thứ 3 của bạn.

5

Bạn đang hỏi "Tại sao trình biên dịch phiên dịch (2) lại giống như (3)?". Vâng, bởi vì trong ngôn ngữ C++ (cũng như trong C) họ ngữ nghĩa giống nhau.Khi bạn định nghĩa một typename như

typedef int *IntPtr; 

sau đó loại const IntPtr sẽ đại diện cho int *const, không phải cho const int *. Đó chỉ là cách typedef-tên làm việc trong C + +.

Tên đã nhập trong C++ không phải là macro. Mặc dù chúng không xác định các kiểu mới (chỉ là bí danh cho các kiểu hiện có), nhưng các bí danh kết quả vẫn là "nguyên tử", "nguyên khối" theo nghĩa nào đó bất kỳ vòng loại nào được áp dụng cho bí danh sẽ áp dụng là vòng loại cấp cao nhất. Khi bạn đang làm việc với một typedef tên, không có cách nào để "lẻn vào" một vòng loại const để nó bằng cách nào đó sẽ "xuống" đến một phần cấp thấp hơn của loại (int trong trường hợp của bạn).

Nếu bạn nhấn mạnh vào việc sử dụng typedef-tên, bạn không có sự lựa chọn trực tiếp nào khác ngoài việc cung cấp hai typedef-tên gọi khác nhau, như

typedef int *IntPtr; 
typedef const int *ConstIntPtr; 

và sử dụng ConstIntPtr khi bạn cần một phiên bản con trỏ-to-const của loại.

+0

+1, câu trả lời hay :-) –

0

Tôi chắc chắn bạn biết rằng const IntPtrIntPtr const là cùng loại. Có nghĩa là list<const IntPtr>list<IntPtr const> là cùng loại. Có nghĩa là bạn đang cố gắng biên dịch điều này:

typedef int * IntPtr; 
     list<IntPtr const> int_pointers; // (2bis) 
Các vấn đề liên quan