2012-07-12 20 views
8

Từ hiểu biết của tôi, mutable hủy constness của một biếnconst_cast VS có thể thay đổi? bất kỳ sự khác biệt?

Class A { 
    void foo() const { 
    m_a = 5; 
} 
mutable int m_a; 
}; 

Nhưng cũng const_cast:

void print (char * str) 
{ 
    cout << str << endl; 
} 

int main() { 
    const char * c = "this is a line"; 
    print (const_cast<char *> (c)); 
    return 0; 
} 

Vì vậy, thay đổi những gì một từ khác?

Cảm ơn

Trả lời

16

const_cast không thể hủy bỏ độ chói của đối tượng. const_cast chỉ có thể xóa constness khỏi đường dẫn truy cập cho một đối tượng. Đường dẫn truy cập là một con trỏ hoặc một tham chiếu đến một đối tượng. Việc xóa bỏ constness khỏi đường dẫn truy cập hoàn toàn không ảnh hưởng đến chính đối tượng đó. Ngay cả khi bạn sử dụng const_cast để xóa độ mờ của đường dẫn truy cập, điều đó vẫn không nhất thiết cho phép bạn sửa đổi đối tượng. Cho dù bạn có thể làm điều đó hay không vẫn phụ thuộc vào chính đối tượng đó. Nếu đó là const, bạn không được phép sửa đổi nó và bất kỳ nỗ lực nào để làm như vậy sẽ dẫn đến hành vi không xác định.

Ví dụ này minh hoạ mục đích sử dụng của const_cast

int i = 5; // non-constant object 
    const int *p = &i; // `p` is a const access path to `i` 

    // Since we know that `i` is not a const, we can remove constness... 
    int *q = const_cast<int *>(p); 
    // ... and legally modify `i` 
    *q = 10; 
    // Now `i` is 10 

Lý do duy nhất ở trên là hợp pháp và hợp lệ là một thực tế rằng i thực sự là một tổ chức phi liên tục đối tượng , và chúng tôi biết về nó .

Nếu đối tượng ban đầu là thực sự liên tục, sau đó các mã trên sẽ tạo ra hành vi undefined:

const int j = 5; // constant object 
    const int *p = &j; // `p` is a const access path to `j` 

    int *q = const_cast<int *>(p); // `q` is a non-const access path to `j` 
    *q = 10; // UNDEFINED BEHAVIOR !!! 

ngôn ngữ C++ không cho phép bạn chỉnh sửa các đối tượng liên tục và const_cast là hoàn toàn bất lực ở đây, bất kể cách bạn sử dụng nó.

mutable là một điều hoàn toàn khác. mutable tạo một dữ liệu được lưu có thể được sửa đổi một cách hợp pháp ngay cả khi đối tượng chứa được khai báo const. Theo nghĩa đó, mutable không cho phép bạn sửa đổi [một số phần được chỉ định của] đối tượng liên tục. const_cast, mặt khác, không thể làm bất cứ điều gì như thế.

1

Sự khác biệt là ngữ nghĩa - i. e. cùng một mã được tạo ra, cùng một kết quả thời gian chạy (const ness là một cấu trúc hoàn toàn biên dịch-thời gian anyway), nhưng hai cấu trúc truyền đạt một ý nghĩa hơi khác nhau.

Ý tưởng là bạn sử dụng mutable cho các biến nằm trong lớp, nhưng không cấu thành trạng thái của đối tượng. Ví dụ cổ điển là vị trí hiện tại trong một đối tượng blob. Điều hướng trong blob không được tính là "sửa đổi" đốm màu theo cách quan trọng. Bằng cách sử dụng mutable, bạn đang nói "biến này có thể thay đổi, nhưng đối tượng vẫn như cũ". Bạn đang nói rằng đối với lớp học đặc biệt này, const -ness không có nghĩa là "tất cả các biến bị đóng băng".

const_cast, theo cách khác, có nghĩa là bạn đang vi phạm chính xác const hiện tại và hy vọng sẽ tránh được điều đó. Có lẽ vì bạn đang làm việc với API của bên thứ ba không tôn trọng const (ví dụ: trường học cũ dựa trên C).

4

Sự khác biệt là const_cast không thể gian lận, nhưng mutable là ngoại lệ đối với các quy tắc.

Trên đoạn đầu tiên m_amutable và do đó ngoại lệ đối với quy tắc mà bạn không thể sửa đổi thành viên dữ liệu trên các chức năng thành viên const.

Trên đoạn thứ hai, const_cast cố gắng để lừa, nhưng thực sự không thể: khi loại đã thay đổi, sửa đổi thực tế không được phép: chuỗi thực sự là const. Cố gắng sửa đổi nó sẽ khiến chương trình thể hiện hành vi không xác định.

0

Chỉ cần đặt, tuyên bố biến thành viên là mutable làm cho nó có thể truy cập được từ mọi phương thức không đổi của lớp đó mà không có bất kỳ cú pháp đặc biệt nào khác. const_cast mặt khác phải được thực hiện bất cứ khi nào bạn muốn ghi truy cập vào một biến khác không đổi, và biến đó thậm chí không phải là một thành viên lớp.

Trừ khi bạn muốn cho phép rõ ràng cho phép ghi vào biến thành viên, sử dụng const_cast trong mọi trường hợp vi phạm chính xác const được ưu tiên, nếu chỉ nêu rõ ý định của bạn.

Lưu ý phụ, bạn cũng có thể sử dụng const_cast để thêm hoặc xóa công cụ sửa đổi volatile.

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