Mặc dù đúng là hành vi được xác định rõ - không đúng khi trình biên dịch có thể "tối ưu hóa cho const" theo nghĩa mà bạn muốn nói.
Nghĩa là, một trình biên dịch không được phép giả định rằng chỉ vì một tham số là a const T* ptr
, bộ nhớ được trỏ bởi ptr
sẽ không bị thay đổi thông qua một con trỏ khác. Các con trỏ thậm chí không phải bằng nhau. Đây const
là một nghĩa vụ, không phải là sự bảo đảm - nghĩa vụ của bạn (= chức năng) không được thực hiện thay đổi thông qua con trỏ đó.
Để thực sự có sự đảm bảo đó, bạn cần đánh dấu con trỏ bằng restrict
từ khóa. Vì vậy, nếu bạn biên dịch hai hàm này:
int foo(const int* x, int* y) {
int result = *x;
(*y)++;
return result + *x;
}
int bar(const int* x, int* restrict y) {
int result = *x;
(*y)++;
return result + *x;
}
các foo()
chức năng phải đọc hai lần từ x
, trong khi bar()
chỉ cần đọc nó một lần:
foo:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, DWORD PTR [rdi] # second read
ret
bar:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, eax # no second read
ret
Xem này trực tiếp trên GodBolt.
restrict
chỉ là một từ khóa trong C (kể từ C99); thật không may, cho đến nay nó vẫn chưa được đưa vào C ++ (vì lý do nghèo nàn mà việc giới thiệu nó trong C ++) phức tạp hơn. Nhiều trình biên dịch hỗ trợ nó, tuy nhiên, như __restrict
.
Dòng dưới cùng: Trình biên dịch phải hỗ trợ trường hợp sử dụng "bí truyền" của bạn khi biên dịch f()
và sẽ không có bất kỳ vấn đề nào với nó.
Xem bài này liên quan đến các trường hợp sử dụng cho restrict
.
const
không phải là một nghĩa vụ của bạn (= hàm) không được thực hiện thay đổi thông qua con trỏ đó. Tiêu chuẩn C cho phép chức năng loại bỏconst
thông qua truyền và sau đó sửa đổi đối tượng thông qua kết quả. Về cơ bản,const
chỉ là tư vấn và thuận tiện cho lập trình viên để giúp tránh vô tình sửa đổi một đối tượng.