các loại vấn đề Chandler đã nói về có thể dễ dàng được minh họa bằng một đơn giản strcpy
:
char *stpcpy (char * dest, const char * src);
Khi thực hiện thao tác này, bạn có thể giả định rằng bộ nhớ được trỏ đến bởi dest
hoàn toàn tách biệt với bộ nhớ được trỏ đến bởi src
. Trình biên dịch) có thể muốn tối ưu hóa nó bằng cách đọc một khối ký tự từ chuỗi được trỏ đến bởi src
và viết tất cả chúng một lần vào dest
. Nhưng nếu dest
chỉ đến một byte trước src
, hành vi của điều này sẽ khác với bản sao ký tự theo từng ký tự đơn giản.
Ở đây vấn đề bí danh là src
có thể bí danh dest
và mã được tạo phải được thực hiện kém hiệu quả hơn nếu có thể là src
không được phép bí danh dest
.
Các thực strcpy
sử dụng một từ khóa phụ, Restrict (đó là technically only part of C, not C++, mà nói với trình biên dịch cho rằng src
và dest
không chồng chéo lên nhau, và điều này cho phép trình biên dịch để tạo ra mã nhiều hiệu quả hơn.
Đây là một ví dụ đơn giản hơn, nơi chúng ta có thể thấy sự khác biệt lớn trong hội đồng:
void my_function_1(int* a, int* b, int* c) {
if (*a) *b = *a;
if (*a) *c = *a;
}
void my_function_2(int* __restrict a, int* __restrict b, int* __restrict c) {
if (*a) *b = *a;
if (*a) *c = *a;
}
Giả sử đây là sự đơn giản hóa chức năng nó thực sự có ý nghĩa khi sử dụng hai câu lệnh if chứ không phải chỉ là if (*a) { *b=*a; *c=*a; }
, nhưng mục đích là như nhau.
Chúng tôi có thể giả định khi viết điều này a != b
vì có một số lý do tại sao nó sẽ không có ý nghĩa đối với my_function
được sử dụng như thế.Nhưng trình biên dịch không thể giả định rằng, và làm một cửa hàng của b
và tái tải của a
từ bộ nhớ trước khi thực hiện dòng thứ hai, để trang trải các trường hợp b == a
:
0000000000400550 <my_function_1>:
400550: 8b 07 mov (%rdi),%eax
400552: 85 c0 test %eax,%eax <= if (*a)
400554: 74 0a je 400560 <my_function_1+0x10>
400556: 89 06 mov %eax,(%rsi)
400558: 8b 07 mov (%rdi),%eax
40055a: 85 c0 test %eax,%eax <= if (*a)
40055c: 74 02 je 400560 <my_function_1+0x10>
40055e: 89 02 mov %eax,(%rdx)
400560: f3 c3 repz retq
Nếu chúng ta loại bỏ nguy cơ răng cưa bằng cách thêm __restrict
, trình biên dịch tạo ra mã ngắn hơn và nhanh hơn:
0000000000400570 <my_function_2>:
400570: 8b 07 mov (%rdi),%eax
400572: 85 c0 test %eax,%eax
400574: 74 04 je 40057a <_Z9my_function_2PiS_S_+0xa>
400576: 89 06 mov %eax,(%rsi)
400578: 89 02 mov %eax,(%rdx)
40057a: f3 c3 repz retq
Tại sao bạn không hỏi Chandler Carruth? –
có thể trùng lặp [bí danh nghiêm ngặt] (http://stackoverflow.com/questions/754929/strict-aliasing) –
Thử xem [this] (http://cslibrary.stanford.edu/104/). Nó thực sự khá tốt.Bí danh là khi bạn lấy con trỏ của một objecct thay vì đối tượng mình, như ông giải thích. –