26

我对此有一个大致的了解,restrict但我希望能澄清一些要点。我有一个函数,它从一个缓冲区读取一个以空字符结尾的字符串,并在另一个缓冲区中写出一个 URL 编码版本。该函数有这个签名(目前没有restrict):

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

unencoded是我的以 null 结尾的源字符串。目标缓冲区由encodedand表示encodedEnd,其中encoded指向缓冲区中的第一个字符charencodedEnd指向缓冲区之后的第一个字符,即该函数将chars 写入但不包括指向的位置encodedEnd- 这是您的基本begin/end迭代器如果您熟悉 C++ STL 约定,请配对。

如果我添加restrict到这个函数,它应该只应用于前两个参数:

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

或者将它添加到所有三个参数中是否有一些我不理解的好处?

我可以看到制作输入和输出缓冲区restrict有助于编译器知道它们不重叠。但由于最后一个参数 ,encodedEnd仅用于标记输出缓冲区的结束,我认为这restrict对编译器没有任何帮助(尽管我认为它不会伤害,除了增加不必要的噪音到函数声明)。

4

3 回答 3

12

在此处尝试 Mike Acton 的文章(旧链接)。限制是可怕的,因为不使用它的性能影响和错误使用它的后果。

在您的情况下,听起来您可以安全地将限制应用于所有三个指针,因为没有别名相同的内存区域。但是,在第三个指针上使用它几乎没有性能优势。

于 2009-05-07T05:49:33.950 回答
7

在这种特殊情况下,无论encodedEnd是否是限制都不会产生影响;您已向编译器承诺,没有人将unencodedencoded别名化,因此读取和写入不会相互干扰。

在这种情况下,restrict 很重要的真正原因是,没有它,编译器无法知道通过encode写入不会影响通过unencoded读取。例如,如果

encoded == unencoded+1

那么每次对编码的写入都会影响从unencoded的每次后续读取,因此编译器在写入完成之前无法安排加载。restrict 向编译器承诺这两个指针不会影响相同的内存,因此它可以将加载安排得足够远以避免管道停顿。

于 2009-05-07T23:56:18.317 回答
4

我认为你是对的,它不会受到伤害。您的循环指针(称为 p)将在循环结束时等于 encodedEnd。但是在循环之后(从 p 或 encodedEnd)不需要访问任何内容,所以这应该不是问题。我认为它也无济于事,因为没有任何东西可以从 encodedEnd 写入或读取,因此没有什么可以优化的。

但我同意你的前两个限制应该真的有帮助。

于 2009-05-07T05:35:15.093 回答