O final constsignifica que a funçãoMethod3 não modifica os membros não mutáveis de sua classe.
const int* constsignifica um ponteiro constante para um int constante: ou seja, um ponteiro que não pode ser alterado, para um int que não pode ser alterado: a única diferença entre isso e const int&é que pode sernull
const int* const&significa uma referência a um ponteiro constante para um int constante. Normalmente, os ponteiros não são passados por referência; const int* &faz mais sentido porque significaria que o ponteiro poderia ser alterado durante a chamada do método, que seria a única razão que vejo para passar um ponteiro por referência, const int* const&é para todas as intenções e finalidades iguais, const int* constexceto que é provavelmente menos eficiente como ponteiros são tipos de dados antigos simples (POD) e devem, em geral, ser passados por valor.
# 5 diz que toda a declaração de função à esquerda é const, o que implica que esta é necessariamente uma função-membro em vez de uma função livre.
# 4 diz que o ponteiro à esquerda é const(não pode ser alterado para apontar para um endereço diferente).
# 3 diz que o intà esquerda é const(não pode ser alterado para ter um valor diferente).
# 2 diz que o ponteiro à esquerda é const.
# 1 diz que intà esquerda éconst .
Juntando tudo isso, você pode ler isso como uma constfunção de membro chamada Method3que faz referência a um constponteiro para um int const(ou a const int, se preferir) e retorna um constponteiro para um int const( const int).
Em primeiro lugar, const Té equivalente a T const.
const int* consté portanto equivalente a int const * const.
Ao ler expressões com muitos consttokens e ponteiros, sempre tente lê-los da direita para a esquerda (após aplicar a transformação acima). Portanto, neste caso, o valor de retorno é um ponteiro const para um constint . Fazer o próprio ponteiro não constfaz sentido aqui, pois o valor de retorno não é um lvalue que pode ser modificado. Fazer a ponta const, entretanto, garante que o chamador não pode modificar o int(ou array de ints) retornado por Method3.
const int*const&torna-se int const*const&, portanto, é uma referência a um ponteiro const para um constint . Passar um ponteiro const por referências masculinas também não faz sentido - você não pode modificar o valor referenciado já que o ponteiro é conste as referências e ponteiros ocupam armazenamento igual, então não há nenhuma economia de espaço também.
O último constindica que o método não modifica o thisobjeto. O thisponteiro dentro do corpo do método terá a declaração (teórica) T const * const this. Isso significa que um const T*objeto será capaz de chamar T::Method3().
Votando isso (e a resposta semelhante de ildjarn), em parte por deixar claro que a coisa toda faz mais sentido se você não colocar o primeiro consts no início da frase. É precisamente por isso que acho uma má prática colocar constlá, embora a linguagem o permita, e é o uso mais comum.
TED de
12
Uma maneira fácil de lembrar as regras do consté pensar da seguinte maneira: constaplica-se à coisa à sua esquerda, a menos que não haja nada à sua esquerda.
Portanto, no caso de const int * const, a primeira const não tem nada à sua esquerda, então ela se aplica a inte a segunda tem algo à sua esquerda, então ela se aplica ao ponteiro.
Esta regra também informa o que aconteceria no caso de você ter const int const *. Uma vez que ambos os constantes se aplicam a intesta expressão, é redundante e, portanto, inválido.
const/* don't modify the int or array of ints' value(s) */int*const/* as a retval, ignored. useless declaration */Method3(const/* don't modify the int or array of ints' value(s) */int*const/* don't modify the pointer's value, the address to which `pointer` points to. e.g. you cannot say `++pointer` */&)const;/* this method does not modify the instance/object which implements the method */
Eu gosto de usar o método "relógio" ou "espiral" onde, começando com o nome do identificador (neste caso Method3), você lê da esquerda para a direita e vice-versa, etc. para decodificar convenções de nomenclatura. Portanto, const int* const Method3(const int* const&) consté um método de classe que não altera nenhum membro da classe (de alguma classe sem nome) e faz uma referência constante a um ponteiro que aponta para uma constante inte retorna um ponteiro constante para uma constante int.
Uma maneira fácil de lembrar o const em C ++ é quando você vê algum código na forma de:
XXX const;const YYY;
XXX, YYY será um componente constante, XXX constforma:
function ( def var )const;------#1*const;------#2
const YYY Formato:
constint;------#3constdouble;
As pessoas costumam usar esses tipos. Quando você vir em "const&"algum lugar, não se sinta confuso, const está descrevendo algo antes de si mesmo. portanto, a resposta a esse problema é evidente agora.
Eu só quero mencionar que const int* const&é de fato uma referência constante a const int*. Por exemplo:
int i =0;int j =1;int* p =&i;int* q =&j;constint*const& cpref = p;
cpref = q;//Error: assignment of read-only reference 'cpref'
É também o caso de int* const&, O que significa: "Uma referência constante a int*".
Mas const int*&é uma referência não constante a const int*.
Espero que isto ajude.
const # 1: O ponteiro retornado por Method3 se refere a um const int.
const # 2: O valor do ponteiro retornado pela própria função é const. Esta é uma const inútil (embora gramaticalmente válida), porque o valor de retorno de uma função não pode ser um valor l.
const # 3: O tipo de ponteiro passado por referência à função aponta para um const int.
const # 4: O valor do ponteiro passado por referência à função é, ele mesmo, um ponteiro const. Declarar um valor que é passado para uma função como const normalmente seria inútil, mas esse valor é passado por referência, portanto, pode ser significativo.
const # 5: A função (presumivelmente uma função-membro) é const, o que significa que não é permitido (a) atribuir novos valores a qualquer membro do objeto do qual faz parte ou (b) chamar uma função-membro não const sobre o objeto ou qualquer um de seus membros.
const no final do método está o qualificador, significando que o estado do objeto não será alterado.
const int*const&significa receber por referência um ponteiro const para uma localização const. Ele não pode mudar para apontar para um local diferente, nem mudar o valor para o qual está apontando.
const int*const é o valor de retorno que também é um ponteiro constante para um local constante.
Alguns exemplos podem ser bons para demonstrar esse conceito, quanto mais, melhor imho.
classTestClass{private:int iValue;int* oValuePtr;int& oValueRef;public:intTestClass::ByValMethod1(intValue){// Value can be modifiedValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}intTestClass::ByValMethod2(constintValue){// Value *cannot* be modified// Variable is const variableValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}constintTestClass::ByValMethod3(intValue){// Value can be modifiedValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}constintTestClass::ByValMethod4(constintValue){// Value *cannot* be modified// Variable is const variableValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}constintTestClass::ByValMethod5(constintValue)const{// Value *cannot* be modified// Variable is const variableValue++;// iValue *cannot* be modified// Access through a const object
iValue =Value;
iValue +=1;// Return value *cannot* be modified// Access through a const objectreturn++iValue;}int&TestClass::ByRefMethod1(int&Value){// Value can be modifiedValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}int&TestClass::ByRefMethod2(constint&Value){// Value *cannot* be modified// Variable is const variableValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}constint&TestClass::ByRefMethod3(int&Value){// Value can be modifiedValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}constint&TestClass::ByRefMethod4(constint&Value){// Value *cannot* be modified// Variable is const variableValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}constint&TestClass::ByRefMethod5(constint&Value)const{// Value *cannot* be modified// Variable is const variableValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}int*TestClass::PointerMethod1(int*Value){// Value can be modifiedValue++;// oValuePtr can be assigned
oValuePtr =Value;// oValuePtr can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}int*TestClass::PointerMethod2(constint*Value){// Value can be modifiedValue++;// oValuePtr cannot be assigned// const int* to int*
oValuePtr =Value;// oValuePtr can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}constint*TestClass::PointerMethod3(int*Value){// Value can be modifiedValue++;// oValuePtr can be assigned
oValuePtr =Value;// iValue can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}constint*TestClass::PointerMethod4(constint*Value){// Value cannot be modifiedValue++;// oValuePtr *cannot* be assigned// const int* to int*
oValuePtr =Value;// oValuePtr can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}constint*TestClass::PointerMethod5(constint*Value)const{// Value can be modified++Value;// oValuePtr *cannot* be assigned// const int* to int* const// Access through a const object
oValuePtr =Value;// oValuePtr *cannot* be modified// Access through a const object
oValuePtr +=1;// Return value *cannot* be modifiedreturn++oValuePtr;}};
Respostas:
Leia isto: https://isocpp.org/wiki/faq/const-correctness
O final
const
significa que a funçãoMethod3
não modifica os membros não mutáveis de sua classe.const int* const
significa um ponteiro constante para um int constante: ou seja, um ponteiro que não pode ser alterado, para um int que não pode ser alterado: a única diferença entre isso econst int&
é que pode sernull
const int* const&
significa uma referência a um ponteiro constante para um int constante. Normalmente, os ponteiros não são passados por referência;const int* &
faz mais sentido porque significaria que o ponteiro poderia ser alterado durante a chamada do método, que seria a única razão que vejo para passar um ponteiro por referência,const int* const&
é para todas as intenções e finalidades iguais,const int* const
exceto que é provavelmente menos eficiente como ponteiros são tipos de dados antigos simples (POD) e devem, em geral, ser passados por valor.fonte
É mais fácil de entender se você reescrever isso como o equivalente completamente
em seguida, leia da direita para a esquerda.
# 5 diz que toda a declaração de função à esquerda é
const
, o que implica que esta é necessariamente uma função-membro em vez de uma função livre.# 4 diz que o ponteiro à esquerda é
const
(não pode ser alterado para apontar para um endereço diferente).# 3 diz que o
int
à esquerda éconst
(não pode ser alterado para ter um valor diferente).# 2 diz que o ponteiro à esquerda é
const
.# 1 diz que
int
à esquerda éconst
.Juntando tudo isso, você pode ler isso como uma
const
função de membro chamadaMethod3
que faz referência a umconst
ponteiro para umint const
(ou aconst int
, se preferir) e retorna umconst
ponteiro para umint const
(const int
).(Nb # 2 é totalmente supérfluo .)
fonte
Em primeiro lugar,
const T
é equivalente aT const
.const int* const
é portanto equivalente aint const * const
.Ao ler expressões com muitos
const
tokens e ponteiros, sempre tente lê-los da direita para a esquerda (após aplicar a transformação acima). Portanto, neste caso, o valor de retorno é um ponteiro const para um constint
. Fazer o próprio ponteiro nãoconst
faz sentido aqui, pois o valor de retorno não é um lvalue que pode ser modificado. Fazer a pontaconst
, entretanto, garante que o chamador não pode modificar oint
(ou array deint
s) retornado porMethod3
.const int*const&
torna-seint const*const&
, portanto, é uma referência a um ponteiro const para um constint
. Passar um ponteiro const por referências masculinas também não faz sentido - você não pode modificar o valor referenciado já que o ponteiro éconst
e as referências e ponteiros ocupam armazenamento igual, então não há nenhuma economia de espaço também.O último
const
indica que o método não modifica othis
objeto. Othis
ponteiro dentro do corpo do método terá a declaração (teórica)T const * const this
. Isso significa que umconst T*
objeto será capaz de chamarT::Method3()
.fonte
const
s no início da frase. É precisamente por isso que acho uma má prática colocarconst
lá, embora a linguagem o permita, e é o uso mais comum.Uma maneira fácil de lembrar as regras do
const
é pensar da seguinte maneira:const
aplica-se à coisa à sua esquerda, a menos que não haja nada à sua esquerda.Portanto, no caso de
const int * const
, a primeira const não tem nada à sua esquerda, então ela se aplica aint
e a segunda tem algo à sua esquerda, então ela se aplica ao ponteiro.Esta regra também informa o que aconteceria no caso de você ter
const int const *
. Uma vez que ambos os constantes se aplicam aint
esta expressão, é redundante e, portanto, inválido.fonte
fonte
Eu gosto de usar o método "relógio" ou "espiral" onde, começando com o nome do identificador (neste caso
Method3
), você lê da esquerda para a direita e vice-versa, etc. para decodificar convenções de nomenclatura. Portanto,const int* const Method3(const int* const&) const
é um método de classe que não altera nenhum membro da classe (de alguma classe sem nome) e faz uma referência constante a um ponteiro que aponta para uma constanteint
e retorna um ponteiro constante para uma constanteint
.Espero que isto ajude,
Jason
fonte
Uma maneira fácil de lembrar o const em C ++ é quando você vê algum código na forma de:
XXX, YYY será um componente constante,
XXX const
forma:const YYY
Formato:As pessoas costumam usar esses tipos. Quando você vir em
"const&"
algum lugar, não se sinta confuso, const está descrevendo algo antes de si mesmo. portanto, a resposta a esse problema é evidente agora.fonte
Eu só quero mencionar que
const int* const&
é de fato uma referência constante aconst int*
. Por exemplo:É também o caso de
int* const&
, O que significa: "Uma referência constante aint*
".Mas
const int*&
é uma referência não constante aconst int*
.Espero que isto ajude.
fonte
Ler da direita para a esquerda facilita a compreensão dos modificadores.
Um método const que faz referência a um ponteiro const para um const int chamado
Method3
que retorna um ponteiro const para um const int.mutable
)fonte
const # 1: O ponteiro retornado por Method3 se refere a um const int.
const # 2: O valor do ponteiro retornado pela própria função é const. Esta é uma const inútil (embora gramaticalmente válida), porque o valor de retorno de uma função não pode ser um valor l.
const # 3: O tipo de ponteiro passado por referência à função aponta para um const int.
const # 4: O valor do ponteiro passado por referência à função é, ele mesmo, um ponteiro const. Declarar um valor que é passado para uma função como const normalmente seria inútil, mas esse valor é passado por referência, portanto, pode ser significativo.
const # 5: A função (presumivelmente uma função-membro) é const, o que significa que não é permitido (a) atribuir novos valores a qualquer membro do objeto do qual faz parte ou (b) chamar uma função-membro não const sobre o objeto ou qualquer um de seus membros.
fonte
const
no final do método está o qualificador, significando que o estado do objeto não será alterado.const int*const&
significa receber por referência um ponteiro const para uma localização const. Ele não pode mudar para apontar para um local diferente, nem mudar o valor para o qual está apontando.const int*const
é o valor de retorno que também é um ponteiro constante para um local constante.fonte
Alguns exemplos podem ser bons para demonstrar esse conceito, quanto mais, melhor imho.
Eu espero que isso ajude!
fonte