Pergunta

US $ 5.2.11/7 - [Nota: Dependendo do tipo de objeto, uma operação de gravação através do ponteiro, LValue ou ponteiro para membro de dados resultantes de um const_cast que lança um quadro -const -qual68) poderia produzir comportamento indefinido (7.1.5.1). ] "

As palavras desta seção (C ++ 03) são surpreendentes para mim. O que é surpreendente são duas coisas.

a) Em primeiro lugar, o uso de 'maio'. Por que é 'pode'? Outros lugares do padrão são muito definitivos sobre o comportamento indefinido

b) Por que o lançamento é a constência de um objeto originalmente constante, não imediatamente 'comportamento indefinido'. Por que é necessária uma gravação para o UB ser acionado?

Foi útil?

Solução

a) Em primeiro lugar, o uso de 'maio'. Por que é 'pode'? Outros lugares do padrão são muito definitivos sobre o comportamento indefinido

Não olhe muito profundamente para o uso da palavra poderia aqui. O ponto é que, neste caso, eliminar a constência causa comportamento indefinido.

O padrão C ++ usa "May" ou "pode" frequentemente, como em:

1.3.12: comportamento indefinido poderia Também é esperado quando esse padrão internacional omite a descrição de qualquer definição explícita de comportamento.

Ênfase minha. Basicamente, o padrão usa a palavra "maio" como em "é permitido".

b) Por que o lançamento é a constência de um objeto originalmente constante, não imediatamente 'comportamento indefinido'. Por que é necessária uma gravação para o UB ser acionado?

Uma gravação aciona UB porque é possível que os objetos const possam ser armazenados na memória somente leitura em determinadas plataformas.

Outras dicas

Meu entendimento é que será apenas UB se o objeto em questão for fundamentalmente um objeto const, em vez de um ponteiro const ou referência a um objeto que não era originalmente constante.

A idéia é que os dados que são fundamentalmente constantes podem ser carregados em uma parte somente leitura da memória, e escrever para isso simplesmente não vai funcionar. No entanto, é garantido que funcione corretamente se o objeto em questão for fundamentalmente mutável.

Ex:

const int  x = 4;
const int *y = x;

*const_cast<int*>(x) = 3; // UB - the pointed-to object may 
                          // be in read-only memory or whatever.

int        a = 7;
const int *b = a;

*const_cast<int*>(b) = 6; // Not UB - the pointed-to object is 
                          // fundamentally mutable.

Para um comentário abaixo, porque o código parece terrível nos comentários:

Em §7.1. 5.1/4 do padrão, o exemplo dado é:

int i = 2;
const int * cip; // pointer to const int
cip = &i;        // OK: cv-qualified access path to unqualified
...
int* ip;
ip = const_cast <int *>( cip ); // cast needed to convert const int* to int*
*ip = 4;                        // defined: *ip points to i, a non-const object

Portanto, isso é especificamente permitido.

Para sua primeira pergunta, se algo poderia Produza um comportamento indefinido, então isso não o torna menos indefinido.

Para a segunda parte, eu imagino que seja por razões de interoperabilidade. Por exemplo, C não (ou não, antes de C99) ter um const Palavra -chave, portanto, se você deseja passar um objeto const para uma função C, a constência teria que ser descartada. Portanto, o padrão C ++ especifica que isso é permitido desde que nenhuma gravação seja realizada. Se a função C for somente leitura, a constência poderá ser descartada com segurança.

Mesmo em C ++, a correção inconsistente ou incompleta também é bastante comum. Então, ocasionalmente, encontramos situações em que temos que expulsar a constância para passar um objeto const para uma função que não modifica seu argumento, mas o leva por não-consagimento.

Eu acreditaria que é porque um const O objeto pode ser armazenado na memória somente leitura. Assim, escrever para ele pode ter muitos efeitos diferentes: falha do programa, falha de segmentação ou nenhum efeito.

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