2010-03-24 29 views
12

không const Tôi là một chút nhầm lẫn gì đã xảy ra trong đoạn mã sau:Sửa đổi một const qua một con trỏ


const int e = 2; 

int* w = (int*) &e;   // (1) cast to remove const-ness 
*w = 5;      // (2) 

cout << *w << endl;   // (3) outputs 5 
cout << e << endl;    // (4) outputs 2 

cout << "w = " << w << endl; // (5) w points to the address of e 
cout << "&e = " << &e << endl; 

Trong (1), điểm w đến địa chỉ của e. Trong (2), giá trị đó đã được thay đổi thành 5. Tuy nhiên, khi các giá trị của * w và e được hiển thị, các giá trị của chúng khác nhau. Nhưng nếu bạn in giá trị của con trỏ w và & e, chúng có cùng giá trị/địa chỉ.

Cách e vẫn chứa 2, ngay cả khi nó được đổi thành 5? Chúng được lưu trữ ở một vị trí riêng biệt? Hoặc tạm thời? Nhưng làm sao giá trị được chỉ ra bởi w vẫn là địa chỉ của e?

+15

Bạn đang ở trong vùng hành vi không xác định - mọi thứ đều có thể xảy ra. –

+0

Tâm trí của tôi là quá mệt mỏi để xem những gì đang xảy ra, nhưng bạn có thể sử dụng const_cast cho việc này. Nếu bạn hỏi chỉ để hiểu những gì đang xảy ra, bạn có thể bỏ qua nhận xét này. – erelender

+3

@erelender: Bạn có thể sử dụng 'const_cast' cho điều này nhưng nó sẽ không làm cho hành vi bất kỳ ít không xác định. –

Trả lời

17

Như tôi đã nói trong bình luận của tôi, một khi bạn đã sửa đổi giá trị const bạn đang ở trong đất hành vi không xác định, do đó, nó không có ý nghĩa nhiều để nói về những gì đang xảy ra. Nhưng cái quái gì ..

cout << *w << endl;   // (3) outputs 5 
cout << e << endl;    // (4) outputs 2 

Tại một đoán, *w đang được đánh giá trong thời gian chạy, nhưng e đang được coi là một thời gian biên dịch liên tục

+0

Có thể ... khả năng khác là trình biên dịch nhận thấy "* w = 5" ngay trước và chèn 5 vào dòng đầu tiên thay vì * w – jpalecek

+0

Tôi đồng ý. Một const int được khởi tạo trong phạm vi sẽ là một hằng số thời gian biên dịch. –

+0

Điều này có nghĩa rằng không chỉ sử dụng đúc một biến const cho một con trỏ không const, kể từ khi sửa đổi thông qua con trỏ mà kết quả đến hành vi không xác định? – jasonline

8

Tôi nghi ngờ rằng bạn đang vấp phải trình biên dịch. Nó không mong đợi bạn để chơi thủ đoạn bẩn với e, vì vậy khi nó nhìn thấy dòng:

cout << e << endl; 

Nó chỉ cần chèn giá trị 2 thay vì tìm giá trị thực tế. Bạn có thể xác minh (hoặc bác bỏ) điều này bằng cách xem xét việc tháo gỡ chương trình của bạn.

+0

+1 cho trò chơi trong lắp ráp –

2

Tôi đoán trình biên dịch sử dụng constness để tối ưu hóa biến và chèn một giá trị cố định vào mã.

3

Điều duy nhất tôi có thể nghĩ đến là trình biên dịch có một số cách tối ưu hóa mã trong một cách mà bất kỳ tài liệu tham khảo để e được thay thế bằng một giá trị của 2 mặc dù nó gán bộ nhớ cho e

nên có hiệu lực (ảnh hưởng?) dòng tại chú thích (4) được 'tối ưu hóa' là

cout << "2" << endln; 
4

Tôi đoán rằng trình biên dịch đã tối ưu hóa đầu ra giá trị. Nó thấy rằng e là const (do đó, nó không thể thay đổi - theo lý thuyết) và thay đổi cout << e << endl; thành cout << 2 << endl;. Tuy nhiên, e vẫn phải tồn tại vì nó được sử dụng bởi w, do đó, w chính xác lấy địa chỉ của nó và sửa đổi giá trị của nó, nhưng bạn không thấy điều đó trong cout.

Đạo đức của câu chuyện - chỉ khai báo mọi thứ const khi bạn thực sự muốn là const. Casting đi const ness không phải là một ý tưởng tốt.

1

này được bao phủ bởi phần [dcl.type.cv]/4 của tiêu chuẩn C++ 14 (trước đó các tiêu chuẩn đã có văn bản tương tự quá):

Trừ rằng bất kỳ thành viên lớp tuyên bố mutable thể được sửa đổi, bất kỳ nỗ lực để sửa đổi một đối tượng const trong kết quả cuộc đời của mình trong hành vi undefined.

e là một đối tượng const, và *w = 5; nỗ lực để sửa đổi đối tượng, do đó kết quả là undefined behavior.

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