2015-02-18 29 views
6

Đoạn mã sau cho phép tôi thay đổi giá trị tại * p2 mặc dù p2 được khai báo bằng const.Sử dụng const và decltype với một biến con trỏ

int *p1; 

const decltype(p1) p2 = new int(100); 
*p2 = 200; 
cout << "*p2: " << *p2 << endl; // Outputs *p2: 200 

Tuy nhiên, nếu tôi sử dụng "int *" thay vì "decltype (p1)", thì trình biên dịch sẽ báo lỗi.

const int * p2 = new int(100); 
*p2 = 200; 
cout << "*p2: " << *p2 << endl; 

error: assignment of read-only location ‘* p2’ 
    *p2 = 200; 
    ^

Tôi đang sử dụng g ++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2.

Có decltype bỏ qua const specifier khi áp dụng trên biến con trỏ?

Trả lời

10

const decltype(p1) p2 có nghĩa là int* const p2.

Điều này có nghĩa là bạn không thể thay đổi p2, nhưng bạn có thể thay đổi những điều đang được chỉ ra.


const T luôn áp dụng const đến cái gọi là "cấp cao nhất" của T. Khi T là loại hỗn hợp (nghĩa là một loại được tạo từ tập hợp các loại cơ bản) thì bạn sẽ phải nhảy qua các vòng nếu bạn muốn áp dụng const cho các cấp thấp hơn.

Khi T là int *, thêm const cấp cao nhất sẽ cung cấp cho int * const. Các * demarcates một mức độ; để xem nội dung bên dưới *, bạn phải xóa thủ công *, áp dụng const, sau đó đặt lại *.

Một giải pháp khả thi là:

const std::remove_pointer<decltype(p1)>::type *p2 = new int(100); 
+0

@quantdev bạn nói đúng, tôi đã sao chép từ một câu trả lời SO khác mà không cần kiểm tra. Có giải pháp nào khác không? –

+0

không phải là tôi biết, vấn đề thú vị .. – quantdev

+0

@quantdev Có 'const std :: remove_reference :: type * p2 = ...;' mặc dù đó là hơi xấu xí –

4

std::pointer_traits sẽ có ích ở đây. std::pointer_traits::element_typestd::pointer_traits::rebind cho phép bạn viết một biểu chung chung mà sẽ làm việc tốt cho bất kỳ loại con trỏ như:

using element_type = std::pointer_traits<decltype(p1)>::element_type; 
using pointer_like_to_const = std::pointer_traits<decltype(p1)>::rebind<std::add_const_t<element_type>>; 
pointer_like_to_const p2 = new int(100); 

Lưu ý rằng đoạn mã này sẽ làm việc ngay cả khi p1shared_ptr<int> hoặc unique_ptr<int>.

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