Sempre tive dúvidas, o que a palavra-chave restringir significa em C ++?
Isso significa que o ponteiro de dois ou mais dados para a função não se sobrepõe? O que mais isso significa?
c++
restrict-qualifier
Esteira
fonte
fonte
restrict
é uma palavra-chave c99. Sim, Rpbert S. Barnes, eu sei que a maioria dos compiladores suporta__restrict__
. Você notará que qualquer coisa com sublinhado duplo é, por definição, específica da implementação e, portanto, NÃO C ++ , mas uma versão específica do compilador.#warning
diretiva comum ou as macros de assinatura de função (__PRETTY_FUNCTION__
no GCC,__FUNCSIG__
no MSVC, etc.).restrict
não é considerada uma palavra-chave C ++ (consulte en.cppreference.com/w/cpp/keyword ) e, de fato, a única mençãorestrict
no padrão C ++ 11 (consulte open-std.org/jtc1/sc22/wg21 /docs/papers/2012/n3337.pdf , uma cópia do FDIS com pequenas alterações editoriais, §17.2 [library.c], página em PDF 413) afirma que:restrict
deve ser omitida (excluída, deixada de fora) assinaturas e semânticas de funções da biblioteca padrão C quando essas funções estão incluídas na biblioteca padrão C ++. Ou, em outras palavras, afirmei o fato de que, se a assinatura de uma função de biblioteca padrão C contiverrestrict
em C, arestrict
palavra - chave deverá ser removida da assinatura do equivalente em C ++.Respostas:
Em seu artigo, Memory Optimization , Christer Ericson diz que, embora
restrict
ainda não faça parte do padrão C ++, ele é suportado por muitos compiladores e recomenda seu uso quando disponível:Nos compiladores C ++ que o suportam, provavelmente deve se comportar da mesma forma que em C.
Veja esta publicação do SO para obter detalhes: Uso realista da palavra-chave 'restringir' C99?
Demore meia hora para folhear o artigo de Ericson, é interessante e vale a pena.
Editar
Também descobri que o compilador AIX C / C ++
__restrict__
da IBM suporta a palavra - chave .O g ++ também parece suportar isso, pois o seguinte programa é compilado corretamente no g ++:
Eu também encontrei um bom artigo sobre o uso de
restrict
:Desmistificando a palavra-chave Restringir
Edit2
Encontrei um artigo que discute especificamente o uso de restringir em programas C ++:
Load-hit-stores e a palavra-chave __restrict
Além disso, o Microsoft Visual C ++ também suporta a
__restrict
palavra - chave .fonte
#ifndef __GNUC__
#define __restrict__ /* no-op */
ou algo parecido. E defina-o como__restrict
se_MSC_VER
estiver definido.Como outros disseram, se não significa nada como no C ++ 14 , vamos considerar a
__restrict__
extensão GCC, que faz o mesmo que o C99restrict
.C99
restrict
diz que dois ponteiros não podem apontar para regiões de memória sobrepostas. O uso mais comum é para argumentos de função.Isso restringe como a função pode ser chamada, mas permite mais otimizações de compilação.
Se o chamador não seguir o
restrict
contrato, comportamento indefinido.O projeto C99 N1256 6.7.3 / 7 "Qualificadores de tipo" diz:
e 6.7.3.1 "Definição formal de restrição" fornece detalhes sangrentos.
Uma possível otimização
O exemplo da Wikipedia é muito esclarecedor.
Mostra claramente como ele permite salvar uma instrução de montagem .
Sem restrição:
Pseudo montagem:
Com restringir:
Pseudo montagem:
O GCC realmente faz isso?
g++
4.8 Linux x86-64:Com
-O0
, eles são os mesmos.Com
-O3
:Para os não iniciados, a convenção de chamada é:
rdi
= primeiro parâmetrorsi
= segundo parâmetrordx
= terceiro parâmetroA saída do GCC foi ainda mais clara que o artigo da wiki: 4 instruções vs 3 instruções.
Matrizes
Até o momento, temos economia de instruções únicas, mas se o ponteiro representar matrizes a serem repetidas, um caso de uso comum, várias instruções podem ser salvas, como mencionado por supercat e michael .
Considere, por exemplo:
Por causa disso
restrict
, um compilador inteligente (ou humano) pode otimizar isso para:O que é potencialmente muito mais eficiente, pois pode ser otimizado para montagem em uma implementação decente da libc (como glibc). É melhor usar std :: memcpy () ou std :: copy () em termos de desempenho? , possivelmente com instruções SIMD .
Sem, restringir, essa otimização não pode ser feita, por exemplo, considere:
Então a
for
versão faz:enquanto a
memset
versão faz:O GCC realmente faz isso?
GCC 5.2.1.Linux x86-64 Ubuntu 15.10:
Com
-O0
, ambos são iguais.Com
-O3
:com restringir:
Duas
memset
chamadas conforme o esperado.sem restrição: sem chamadas stdlib, apenas um loop de 16 iterações que eu não pretendo reproduzir aqui :-)
Não tive paciência para compará-los, mas acredito que a versão restrita será mais rápida.
Regra estrita de alias
A
restrict
palavra-chave afeta apenas ponteiros de tipos compatíveis (por exemplo, doisint*
) porque as regras estritas de aliasing dizem que o aliasing de tipos incompatíveis é um comportamento indefinido por padrão, e assim os compiladores podem assumir que isso não acontece e otimizar.Veja: Qual é a regra estrita de alias?
Isso funciona para referências?
De acordo com os documentos do GCC, ele faz: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Restricted-Pointers.html com sintaxe:
Existe até uma versão para
this
funções-membro:fonte
-fno-strict-aliasing
,restrict
não deve fazer diferença entre ponteiros do mesmo tipo ou tipos diferentes, não? (Estou referindo-se a "Restringir palavra-chave afeta somente ponteiros de tipos compatíveis")restrict
significa algo em C ++. Se você chamar uma função de biblioteca C comrestrict
parâmetros de um programa C ++, terá que obedecer às implicações disso. Basicamente, serestrict
for usado em uma API da biblioteca C, significa algo para qualquer pessoa que a chamar de qualquer idioma, incluindo o FFI dinâmico do Lisp.Nada. Foi adicionado ao padrão C99.
fonte
restrict
como uma palavra-chave. Portanto, minha resposta está correta. O que você descreve é um comportamento específico da implementação e algo em que você realmente não deve confiar.Esta é a proposta original para adicionar esta palavra-chave. Como dirkgently apontou, porém, este é um recurso C99 ; não tem nada a ver com C ++.
fonte
__restrict__
palavra - chave que é idêntica até onde eu sei.restrict
. O comportamento do programa C ++ fica indefinido se violar as restrições implícitas porrestrict
.restrict
palavra - chave. Obviamente, se você passar ponteiros com alias para uma função C que os declara restritos (o que você pode fazer com C ++ ou C), isso é indefinido, mas isso é com você.restrict
. O comportamento do programa C ++ fica indefinido se violar as restrições implícitas pelo restringir. Mas isso realmente não tem nada a ver com C ++, porque está "em você".Não existe tal palavra-chave em C ++. A lista de palavras-chave C ++ pode ser encontrada na seção 2.11 / 1 do padrão da linguagem C ++.
restrict
é uma palavra-chave na versão C99 da linguagem C e não em C ++.fonte
__restrict__
palavra - chave que é idêntica até onde eu sei.Como os arquivos de cabeçalho de algumas bibliotecas C usam a palavra-chave, a linguagem C ++ precisará fazer algo a respeito. No mínimo, ignorando a palavra-chave, para que não tenhamos que # definir a palavra-chave em uma macro em branco para suprimi-la. .
fonte
extern C
declaração ou sendo descartada silenciosamente, como é o caso do compilador AIX C / C ++, que manipula a__rerstrict__
palavra - chave. Essa palavra-chave também é suportada no gcc, para que o código compile o mesmo no g ++.