Вопрос

У меня есть общее представление о restrict , но я надеюсь уточнить некоторые тонкости. У меня есть функция, которая читает строку с нулевым символом в конце из одного буфера и записывает кодированную версию URL в другой буфер. Функция имеет эту подпись (в настоящее время без restrict ):

char const *StringUrlEncode(char const *unencoded, 
                            char *encoded,
                            char *encodedEnd);

unencoded - моя исходная строка с нулевым символом в конце. Целевой буфер представлен encoded и encodedEnd , где encoded указывает на первый char в буфере и < code> encodedEnd указывает на первый символ после буфера, т.е. функция будет записывать char до, но не включая расположение, на которое указывает encodedEnd - это ваша основная пара итераторов begin / end , если вы знакомы с соглашениями C ++ STL.

Если я добавлю restrict к этой функции, ее следует применять только к первым двум параметрам:

char const *StringUrlEncode(char const *restrict unencoded, 
                            char *restrict encoded,
                            char *encodedEnd);

или есть какая-то польза, которую я не понимаю, добавляя ее ко всем трем параметрам?

Я вижу, что создание буферов ввода и вывода restrict помогает компилятору понять, что они не перекрываются. Но поскольку последний параметр, encodedEnd , используется только для обозначения конца выходного буфера, я думаю, что restrict действительно не поможет компилятору здесь (хотя я предполагаю, что это не повредит, кроме добавления ненужного шума в объявление функции).

Это было полезно?

Решение

Воспользуйтесь статьей Майка Актона здесь . Ограничение является пугающим из-за последствий для производительности, связанных с его неиспользованием, и последствий его неправильного использования.

В вашем случае кажется, что вы могли бы безопасно применить ограничение ко всем трем указателям, поскольку ни один из них не является псевдонимом одной и той же области памяти. Однако при использовании его в качестве третьего указателя выигрыш в производительности будет незначительным.

Другие советы

В этом конкретном случае не имеет значения, является ли encodedEnd ограниченным или нет; вы пообещали компилятору, что никто не будет псевдонимами unencoded и encoded , поэтому чтение и запись не будут мешать друг другу.

Настоящая причина ограничения в этом случае важна в том, что без него компилятор не может знать, что запись через кодированный не повлияет на чтение через незашифрованный . Например, если

encoded == unencoded+1

тогда каждая запись в кодированный будет влиять на каждое последующее чтение из незашифрованного , поэтому компилятор не может запланировать загрузку до завершения записи. restrict обещает компилятору, что два указателя не влияют на одну и ту же память, поэтому он может планировать загрузки достаточно далеко вперед, чтобы избежать остановок конвейера.

Я думаю, ты прав, что это не повредит. Ваш указатель цикла (назовите его p) будет равен encodedEnd в конце цикла. Но ничего не нужно делать после цикла (из p или encodedEnd), так что это не должно быть проблемой. Я тоже не думаю, что это поможет, потому что ничего не пишется и не читается из encodedEnd, поэтому нет ничего, что можно было бы оптимизировать.

Но я согласен с тем, что первые два ограничения действительно должны помочь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top