Pergunta

Em C, não podemos usar e para descobrir o endereço de uma variável registo, mas em C ++ que pode fazer o mesmo. Por que é legal em C ++, mas não em C? Alguém pode explicar este conceito em profundidade.

Foi útil?

Solução

Aqui está um trecho da Seção 6.7.1 (nota 101) do padrão C99 (pdf) :

A implementação pode tratar qualquer declaração register simplesmente como uma declaração auto. No entanto, ou não de armazenamento endereçável é efectivamente utilizado, o endereço de qualquer parte de um objeto declarado com registro de armazenamento de classe especificador não pode ser computado , quer explicitamente (por uso do operador & unário como discutido na 6.5.3.2) ou implicitamente (por conversão de um nome de matriz para um ponteiro como discutido em 6.3.2.1). Assim, o único operador que pode ser aplicado a uma matriz declarada com register armazenamento de classe especificador é sizeof.

E a partir Seção 7.1.1, § 3 do padrão C ++ (pdf) :

A register especificador tem a mesma semântica como um especificador de auto juntamente com uma dica para a implementação que o objecto de forma declarada será muito utilizado. [Nota: a dica pode ser ignorado e na maioria das implementações ele será ignorado se o endereço do objeto é tomada. -end nota]

petiscos divertido sobre register

O grupo C ++ (WG21) quer deprecate register :

A palavra-chave register serve muito pouco função, há mais oferta do que um indício de que uma nota diz normalmente é ignorado. Deve-se obsoleto nesta versão da norma, liberando o nome reservado para uso em uma futura norma, bem como auto foi re-utilizado desta vez por ser semelhante inútil.

Notas do março de 2009 reunião:

O consenso do CWG era a favor de depreciativo register.

Veja o que o grupo C99 (WG14) disse sobre register (pdf) em uma reunião:

Acordo

Geral para depreciar a palavra-chave “auto”. Devemos pedir WG21 voltar para o uso prévio de “register” (sem endereço)? Não, isso não vai voar com WG21.

Outras dicas

A palavra-chave registo é apenas uma dica e pode ser ignorado. A maioria dos compiladores C ++ ignorá-lo o tempo todo, mas qualquer C ++ compilador irá ignorá-lo se você tomar o endereço da variável, ou criar uma referência a ele.

Por outro lado, um compilador C ++ não Have para ignorar "registrar" só porque você toma o endereço da variável. Em teoria, o compilador poderia armazená-lo num registo e dar-lhe algum valor ponteiro mágica que de alguma forma está mapeado para o registo nos bastidores, mas isso seria um monte de trabalho por muito pouco ganho, de forma que nenhum compilador (que eu saiba) faz qualquer coisa assim.

Desde registo é ignorável em C, bem como, eu suspeito que a proibição explícita contra a tomada de endereços de variáveis ??de registro era simplesmente para aliviar compiladores C do fardo de verificação para isso.

A parte relevante do C ++ padrão é 7.1.1.3:

Um registo especificador tem a mesma semântica como uma auto especificador juntamente com uma dica para a implementação que o objecto de forma declarada será muito utilizado. [Nota: a dica pode ser ignorado e na maioria das implementações ele será ignorado se o endereço do objeto é tomada. -end nota]

Desculpe a resposta super tarde.

O problema é que, em C, register originalmente significava armazenar valores em um registro que é por que só int e char pode ser usado para isso. Mas com o tempo e C especialmente ++ padrão, é ampliado para "acesso rápido" em vez de "no registo de CPU". Assim, em C ++, um array talvez um tipo register mas sabemos que não é possível armazenar matrizes num registo CPU. Por isso, é logicamente bem para resolver um C ++ registrar (no sentido acima), mas ainda não fará sentido se os valores são realmente num registo CPU.

Eu assumo que a palavra-chave não teria mesmo fez para a língua se não fosse para compatibilidade C. Enquanto eu não posso falar com qualquer autoridade, se é assim, parece-me que há uma razão prática para que seja além legal simplesmente um padrão reforçado "o compilador é mais esperto do que você" cláusula: C ++ leva endereços das coisas sem permissão mais prontamente do que faz C. Especificamente: funções de membro, e referências.

Porque funções membro requerem um parâmetro implícito this, seria impossível chamá-los a partir de um register objeto declarado. Em C, não há nada proibindo-o de dizer register struct X x;, então essa linguagem teria de ser permitido em C ++ [desde C-compatibilidade é toda a razão a palavra-chave ainda existe]. Mas se você proibir chamando funções de membro, bem como tomar endereços, que abrange também a chamada do construtor inicial. Em essência, ele não iria trabalhar em tipos não-POD. Então você acaba com um especificador de classe de armazenamento que é válido apenas para um pequeno subconjunto dos tipos legais, quando todo o resto pode ser usado para qualquer coisa.

Você também pode não criar referências a esses objetos, embora, tecnicamente, o compilador não precisa referências tratar como ponteiros. register int i; int& x; não é obrigado a ter espaço para duas variáveis, mas se você mais tarde fazer &x você acaba com um ponteiro para i. Assim, a construção inicial tem de ser prestados ilegal. Enquanto este parece ser um não-problema, uma vez que as referências não existem no C de qualquer forma, voltando ao nosso ponto anterior, os tipos POD declarado com o especificador register já não pode ser copiado. O construtor de cópia fornecido pelo compilador é do X::X(const X&) forma ou X::X(X&) conforme apropriado.

Assim, a fim de manter a compatibilidade C, eles têm que fazer register única como um especificador de classe de armazenamento na medida em que não se aplica a todos os tipos e modificar pelo menos duas partes diferentes da outra parte padrão [para especificar que você pode não criar uma referência a uma variável declarada com o especificador register, e de alguma forma contornar as referências para POD cópia]. Ou, eles poderiam simplesmente dizer "sua aprovação para tomar o endereço de" e deixe compiladores decidir se quer ou não honrar os pedidos. Algo que eles estavam pensando em fazer de qualquer maneira.

Uma variável registo não tem um endereço, é realizada (pelo menos é suposto ser realizada) num registo cpu. Desde o modificador registo é nada, mas uma dica, se você forçar o compilador para gerar código para extraí-lo do endereço, o modificador será ignorado e você vai acabar com uma variável ordinária realizada na memória.

Para responder diretamente sua pergunta, qualquer um que permite que você leve o endereço de uma variável registo (o seu post original está contradizendo-se ..) permite que você ignore a sua própria dica e deve pelo menos emitir um aviso. IMO a aplicação correcta seria a de não permitir tomar o endereço de uma variável registo.

A coisa importante a lembrar é que "registrar" é apenas uma sugestão para o compilador (um inútil no que, eu nunca vi qualquer melhoria de velocidade, e a maioria dos compiladores, provavelmente, simplesmente ignorá-la). C e C ++ são ambos autorizados a ignorar o seu "conselho" e manter a variável na memória. Claro, se você tomar o endereço da variável, ele irá forçá-lo a ceder um lugar na memória.

C e C ++ apenas tem regras diferentes sobre o que você pode fazer, porque eles são diferentes idiomas. os designers do C ++ decidiu permitir-lhe obter o endereço de uma variável registro, porque ele faz tudo o que não dano; C não permitem que você faça isso porque iria forçá-lo na memória.

Pensando nisso mais, restrição de C é, provavelmente, pela mesma razão que as variáveis ??tiveram de ser declarado no início do bloco-o compilador pode layout memória para variáveis ??como encontrá-las, sem levar em conta como ela é usada mais tarde na a função.

Este é apenas um palpite, mas eu duvido que você pode tomar o endereço de um registo em C ++ porque tal um pensar simplesmente não existe. C ++, provavelmente não utiliza um registo no seu caso particular. Observe que o register qualificador classe de armazenamento é apenas uma dica para o compilador (e mais se não todos os compiladores modernos feliz ignorá-la completamente).

C e C ++ são duas línguas diferentes, com um grande subconjunto comum. É por isso que algumas coisas são diferentes entre eles.

Enquanto eu não entendi sua pergunta, register é (pelo menos em C ++) um indício de que uma variável pode ser acessado com mais frequência, e nada mais. Em C, isso significa que você não pode tomar o endereço com o operador unário &, que fez uma certa quantidade de sentido na época. Nos primeiros dias de C, esperava-se que o compilador pode não incomodar alocação de memória para a variável, e por isso não seria necessariamente um endereço de tomar.

(computadores normalmente têm registros, que são partes de acesso rápido da CPU e, portanto, o armazenamento mais rápida de acesso. Uma variável pode viver num registo, em vez de na memória, se isso causou um melhor desempenho.)

Hoje em dia, quase todos os compiladores são suficientes sofisticado para fazer a sua própria alocação melhor do que a lata programador, portanto, usando register é quase sempre inútil.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top