Explicação do uso do C ++ Const

const int* const Method3(const int* const&) const; 

Alguém pode explicar o uso de cada um dos const?

Leia isto: https://isocpp.org/wiki/faq/const-correctness

O const final significa que a function Method3 não modifica os membros não mutáveis ​​de sua class.

const int* const significa um ponteiro constante para uma constante int: isto é, um ponteiro que não pode ser alterado, para um int que não pode ser alterado: a única diferença entre este e const int& é que ele pode ser null

const int* const& significa uma referência a um ponteiro constante para uma constante int. Normalmente, os pointers 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 pela qual eu posso ver para passar um ponteiro por referência, const int* const& é para todos os intentos e propósitos o mesmo como const int* const exceto que é provavelmente menos eficiente, pois os pointers são tipos de dados antigos (POD) e estes devem, em geral, ser passados ​​por valor.

É mais fácil entender se você reescreve isso como o equivalente

 // v───v───v───v───v───v───v───v───v───v───v───v─┬┐ // ││ // v──#1 v─#2 v──#3 v─#4 #5 int const * const Method3(int const * const&) const; 

depois leia da direita para a esquerda.

# 5 diz que a declaração de function inteira à esquerda é const , o que implica que isso é necessariamente uma function de membro em vez de uma function livre.

# 4 diz que o ponteiro para a esquerda é const (não pode ser alterado para apontar para um endereço diferente).

# 3 diz que o int para a esquerda é const (não pode ser alterado para ter um valor diferente).

# 2 diz que o ponteiro para a esquerda é const .

# 1 diz que o int para a esquerda é const .

Juntando tudo, você pode ler isto como uma function membro const denominada Method3 que leva uma referência a um ponteiro const para um int const (ou um const int , se preferir) e retorna um ponteiro const 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 tokens e pointers constantes, sempre tente lê-los da direita para a esquerda (depois de aplicar a transformação acima). Portanto, neste caso, o valor de retorno é um ponteiro const para um const int . Fazer o próprio ponteiro const não faz sentido aqui, já que o valor de retorno não é um lvalue que poderia ser modificado. Fazer o pointee const , no entanto, garante que o chamador não pode modificar o int (ou array de int s) retornado pelo Method3 .

const int*const& torna const int*const& se int const*const& , portanto, é uma referência a um ponteiro const para um const int . Também não é possível passar um ponteiro const para referências masculinas – não é possível modificar o valor referenciado, pois o ponteiro é const e as referências e os pointers ocupam o mesmo armazenamento, portanto, também não há economia de espaço.

A última const indica que o método não modifica o object this . O ponteiro this dentro do corpo do método terá a declaração (teórica) T const * const this . Isso significa que um object const T* poderá chamar T::Method3() .

Uma maneira fácil de lembrar as regras de const é pensar desta forma: const se aplica à coisa à sua esquerda, a menos que não haja nada à sua esquerda.

Assim, no caso de const int * const , a primeira const não tem nada à sua esquerda, então ela se aplica a int e a segunda tem algo à sua esquerda, então ela se aplica ao ponteiro.

Esta regra também diz o que aconteceria no caso em que você tem const int const * . Uma vez que ambos os const’s se aplicam a int esta expressão é redundante e, portanto, inválida.

Eu gosto de usar o método “clock” ou “spiral”, onde a partir do nome do identificador (neste caso, Method3 ) você lê a frente e para trás da esquerda para a direita, de trás para a esquerda, etc. decodificar convenções de nomenclatura. So const int* const Method3(const int* const&) const é um método de class que não altera nenhum membro da class (de alguma class não nomeada) e faz uma referência constante a um ponteiro que aponta para uma constante int e retorna um ponteiro constante para uma constante int .

Espero que isto ajude,

Jason

 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. eg you cannot say `++pointer` */ &) const; /* this method does not modify the instance/object which implements the method */ 

Ler da direita para a esquerda facilita a compreensão dos modificadores.

Um método const que faz uma referência a um ponteiro const para uma constante int chamada Method3 que retorna um ponteiro const para uma const int.

  1. Um método const não pode modificar membros (a menos que sejam mutable )
  2. Um ponteiro const não pode ser alterado para apontar para outra coisa
  3. Um const int (ou qualquer outro tipo) não pode ser modificado

const # 1: O ponteiro retornado pelo Method3 refere-se a um const int.

const # 2: O valor do ponteiro retornado pela function, em si, é const. Esta é uma constante inútil (embora gramaticalmente válida), porque o valor de retorno de uma function não pode ser um valor-l.

const # 3: O tipo de ponteiro passado por referência à function aponta para um const int.

const # 4: O valor do ponteiro passado por referência à function é, ele próprio, um ponteiro const. Declarar um valor que é passado para uma function como const normalmente seria inútil, mas esse valor é passado por referência, portanto, pode ser significativo.

const # 5: A function (presumivelmente uma function de membro) é const, significando que não é permitido (a) designar novos valores a nenhum membro do object do qual ele faz parte ou (b) chamar uma function de membro não constante no object ou em algum de seus membros.

Uma maneira fácil de lembrar o const em C ++ é quando você vê algum código no formulário como:

 XXX const; const YYY; 

XXX, YYY será um componente constante,
XXX const forma XXX const :

 function ( def var ) const; ------#1 * const; ------#2 

formulário const YYY :

 const int; ------#3 const double; 

As pessoas costumam usar esses tipos. Quando você vê "const&" algum lugar, não se sinta confuso, const está descrevendo algo antes de si mesmo. então a resposta deste problema é evidente agora.

 const int* const Method3(const int* const&) const; | | | | | #3 #2 #3 #2 #1 

Eu só quero mencionar que const int* const& é de fato uma referência constante ao const int* . Por exemplo:

 int i = 0; int j = 1; int* p = &i; int* q = &j; const int* const& cpref = p; cpref = q; //Error: assignment of read-only reference 'cpref' 

É também o caso de int* const& , que significa: “Uma referência constante a int* “.
Mas const int*& é uma referência não constante para const int* .
Espero que isto ajude.

  • const no final do método é o qualificador significando que o estado do object 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 alterar o valor para o qual está apontando.

  • const int*const é o valor de retorno que também é um ponteiro constante para uma localização constante.

Alguns exemplos podem ser bons para demonstrar este conceito, quanto mais melhor ele.

 class TestClass { private: int iValue; int* oValuePtr; int& oValueRef; public: int TestClass::ByValMethod1(int Value) { // Value can be modified Value++; // iValue can be modified iValue = Value; iValue += 1; // Return value can be modified return ++iValue; } int TestClass::ByValMethod2(const int Value) { // Value *cannot* be modified // Variable is const variable Value++; // iValue can be modified iValue = Value; iValue += 1; // Return value can be modified return ++iValue; } const int TestClass::ByValMethod3(int Value) { // Value can be modified Value++; // iValue can be modified iValue = Value; iValue += 1; // Return value can be modified return ++iValue; } const int TestClass::ByValMethod4(const int Value) { // Value *cannot* be modified // Variable is const variable Value++; // iValue can be modified iValue = Value; iValue += 1; // Return value can be modified return ++iValue; } const int TestClass::ByValMethod5(const int Value) const { // Value *cannot* be modified // Variable is const variable Value++; // iValue *cannot* be modified // Access through a const object iValue = Value; iValue += 1; // Return value *cannot* be modified // Access through a const object return ++iValue; } int& TestClass::ByRefMethod1(int& Value) { // Value can be modified Value++; // oValueRef can be modified oValueRef = Value; oValueRef += 1; // Return value can be modified return ++oValueRef; } int& TestClass::ByRefMethod2(const int& Value) { // Value *cannot* be modified // Variable is const variable Value++; // oValueRef can be modified oValueRef = Value; oValueRef += 1; // Return value can be modified return ++oValueRef; } const int& TestClass::ByRefMethod3(int& Value) { // Value can be modified Value++; // oValueRef can be modified oValueRef = Value; oValueRef += 1; // Return value can be modified return ++oValueRef; } const int& TestClass::ByRefMethod4(const int& Value) { // Value *cannot* be modified // Variable is const variable Value++; // oValueRef can be modified oValueRef = Value; oValueRef += 1; // Return value can be modified return ++oValueRef; } const int& TestClass::ByRefMethod5(const int& Value) const { // Value *cannot* be modified // Variable is const variable Value++; // oValueRef can be modified oValueRef = Value; oValueRef += 1; // Return value can be modified return ++oValueRef; } int* TestClass::PointerMethod1(int* Value) { // Value can be modified Value++; // oValuePtr can be assigned oValuePtr = Value; // oValuePtr can be modified oValuePtr += 1; // Return value can be modified return ++oValuePtr; } int* TestClass::PointerMethod2(const int* Value) { // Value can be modified Value++; // oValuePtr cannot be assigned // const int* to int* oValuePtr = Value; // oValuePtr can be modified oValuePtr += 1; // Return value can be modified return ++oValuePtr; } const int* TestClass::PointerMethod3(int* Value) { // Value can be modified Value++; // oValuePtr can be assigned oValuePtr = Value; // iValue can be modified oValuePtr += 1; // Return value can be modified return ++oValuePtr; } const int* TestClass::PointerMethod4(const int* Value) { // Value cannot be modified Value++; // oValuePtr *cannot* be assigned // const int* to int* oValuePtr = Value; // oValuePtr can be modified oValuePtr += 1; // Return value can be modified return ++oValuePtr; } const int* TestClass::PointerMethod5(const int* 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 modified return ++oValuePtr; } }; 

Eu espero que isso ajude!