Тип проблемы Чендлер говорил о можно легко проиллюстрировать с упрощенным strcpy
:
char *stpcpy (char * dest, const char * src);
При написании этой реализации вы можете предположить, что память, на которую указывает dest
, полностью отделена от памяти, на которую указывает src
. Компилятор), возможно, захочет оптимизировать его, читая блок символов из строки, на которую указывает src
, и записывая все их сразу в dest
. Но если dest
указал на один байт перед src
, поведение этого будет отличаться от простой посимвольной копии.
Здесь проблема в том, что сглаживание src
может псевдоним dest
, и сгенерированный код должен быть менее эффективный, чем она могла бы быть, если src
не был разрешен псевдонимом dest
.
Реальный strcpy
использует дополнительное ключевое слово, Restrict (который technically only part of C, not C++, что говорит компилятору предположить, что src
и dest
не пересекаются, и это позволяет компилятору генерировать более эффективный код.
Вот еще более простой пример, где мы можем увидеть большую разницу в сборке:
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;
}
Предположим, что это упрощение функции где на самом деле имеет смысл использовать два if-утверждения, а не только if (*a) { *b=*a; *c=*a; }
, но намерение остается тем же.
Мы можем предположить при написании этого, что a != b
, потому что есть какая-то причина, почему это не имеет смысла для my_function
использовать таким образом.Но компилятор не может предположить, что и делает магазин b
и повторную загрузку a
из памяти перед выполнением второй линии, чтобы покрыть случай, когда 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
Если удалить потенциал для наложения путем добавления __restrict
, компилятор генерирует более короткий и более быстрый код:
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
Почему бы вам не попросить Чандлера Каррута? –
Возможный дубликат [строгий псевдоним] (http://stackoverflow.com/questions/754929/strict-aliasing) –
Попробуйте посмотреть [это] (http://cslibrary.stanford.edu/104/). На самом деле это очень хорошо.Алиасинг - это когда вы берете указатель объекта, а не объект, как он объясняет. –