Diferença entre imutável e const


28

Eu sempre vi os termos immutablee os constusei de forma intercambiável. No entanto, da minha (pequena) experiência, os dois diferem muito no 'contrato' que eles fazem no código:

Imutável torna o contrato que este objeto não será alterado, seja qual for (por exemplo, tuplas Python, seqüências de caracteres Java).

Const faz o contrato de que, no escopo desta variável, ela não será modificada (nenhuma promessa sobre o que outros threads podem fazer com o objeto apontado durante esse período, por exemplo, a palavra-chave C / C ++).

Obviamente, os dois não são equivalentes, a menos que o idioma seja de thread único (PHP) ou tenha um sistema de digitação linear ou de exclusividade (Clean, Mercury, ATS).

Primeiro, meu entendimento desses dois conceitos está correto?

Segundo, se há uma diferença, por que eles são quase exclusivamente usados ​​de forma intercambiável?


1
constnão existe em todos os idiomas, e mutabilidade e imutabilidade não existem em todos os idiomas, portanto, tornar esse idioma agonístico não é aplicável. É específico da linguagem apenas onde esses conceitos se aplicam.

2
Leitura relacionada e recomendada: Tipos de imutabilidade (alguns exemplos de C #, mas amplamente independente do idioma). Alguém deu uma medalha a Eric Lippert.

Respostas:


14

Vou falar com C ++, onde essa diferença é mais relevante.

Como você notou corretamente, imutável significa que um objeto não pode ser alterado após a sua criação. É claro que essa criação pode ocorrer em tempo de execução, ou seja, um constobjeto não é necessariamente uma constante em tempo de compilação. No C ++, um objeto é imutável se (1) e (2) ou (3) forem atendidos:

  1. Ele não possui membros declarados mutableque são alterados por constfunções de membro

  2. É declarado const

  3. constfunções de membro não usam const_castpara remover a constqualificação, a fim de alterar qualquer membro

No entanto, você também pode considerar modificadores de acesso: se uma operação modificar internamente uma instância, mas não afetar o estado da instância observável por meio de sua interface pública, o objeto será "logicamente imutável".

Portanto, o C ++ fornece as ferramentas necessárias para criar objetos imutáveis, mas, como quase tudo no C ++, as ferramentas são minimamente suficientes e requerem diligência para realmente serem usadas. O estado de uma instância não está necessariamente confinado às variáveis ​​de membro da instância - porque o C ++ não fornece uma maneira de impor transparência referencial, pode incluir também o estado global ou de classe.

consttambém possui outra função no C ++: qualificar referências e ponteiros. Uma constreferência pode se referir a um não- constobjeto. É legal (embora geralmente não seja necessário ou aconselhável) usar const_castpara alterar um objeto por meio de uma constreferência, se e somente se esse objeto for declarado não const:

int        i = 4;         // Non-const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Legal.

E é claro que é um comportamento indefinido modificar um constobjeto:

const int  i = 4;         // const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Illegal.

19

Falando em Java, onde a palavra-chave "final" representa "const", considere:

final Person someone = new Person();

Isso significa someoneque NUNCA pode se referir a outro objeto Pessoa. Mas você ainda pode alterar os detalhes da pessoa que está sendo encaminhada. Por exemplosomeone.setMonthlySalary(10000);

Mas, se someonefosse um objeto "Imutável", um dos seguintes seria verdadeiro: (a) Você não teria um método chamado setMonthlySalary (b) Chamar setMonthlySalary sempre lançaria uma exceção comoUnsupportedOperationException


10

Objetos imutáveis ​​são aqueles que não mudam de estado após a criação. Por exemplo;

string prefix = "Pre";
string postfix = "Post";
string myComplexStr = prefix + postfix;

Neste exemplo, o objeto myComplexStr é imutável, mas não constante, pois seu valor é calculado. E é imutável porque é uma string e possui uma propriedade de comprimento estático e não pode ser alterada.

Os objetos Const geralmente são usados ​​para identificar algumas constantes reais cujos valores são conhecidos antes da compilação, como Pi, "USA", "StackOverflow.com", números de porta e assim por diante.

Nesta perspectiva, Const é diferente de Objetos imutáveis ​​porque seus valores não são calculados pelo programa.

Mas se você estiver falando sobre a palavra-chave "const" em C ++, poderá dizer que "const" é usado para criar objetos imutáveis.


1
const em C ++ não cria objetos imutáveis, é apenas um nível de acesso.
Klaim

Você pode explicar como "const double pi = 3.14" não é imutável?
Mert Akcakaya

Bem, depende de onde está. Vamos dizer que sim: "double * p_pi = const_cast <double *> (& pi); * p_pi = 42;" por exemplo. Então, se pi estiver no espaço global ou no espaço de nomes, eu recebo uma falha de segmentação, mas acredito que seja um comportamento indefinido, não um erro específico. Se pi for um membro de qualquer objeto disponível em tempo de execução, que não seja estático, recebo pi == 42. Veja, mesmo usando mutable está disponível porque const em C ++ é sobre nível de acesso, semântico, não imutabilidade de dados, que é quase impossível de obter em C ++. Você pode apenas "simular" isso. const não é imutável.
Klaim

1
@Klaim Mutar algo constassim é um comportamento indefinido, não importa onde ele esteja alocado, IIRC. E o comportamento indefinido é pior do que qualquer erro específico garantido. Isso significa que você não usa mais o C ++ - o C ++ não oferece meios de alterar um constvalor (exceto os mutablemembros, é claro, mas esse não é o seu ponto); portanto, no que diz respeito ao C ++, você não pode fazê-lo. O que implementações específicas permitem é outra questão inteiramente (e aposto que, se você compilar com otimizações, o truque que você executou não afetará as expressões posteriores, piporque foi substituído).

"const em C ++ não cria objetos imutáveis" ainda está errado porque ainda cria constantes globais como você afirmou em sua própria resposta. A palavra-chave é, obviamente, semântica em algum nível; caso contrário, você sempre pode alterar manualmente a tensão de uma célula de memória e alterar o valor de um objeto imutável, se estiver ansioso para usar comportamentos indefinidos.
Mert Akcakaya

8

Primeiro, meu entendimento desses dois conceitos está correto?

Sim, mas sua segunda pergunta mostra que você não entende essas diferenças.

Segundo, se há uma diferença, por que eles são quase exclusivamente usados ​​de forma intercambiável?

constem C ++ é usado apenas para o nível de acesso (significa "somente leitura") , não para imutabilidade. Isso implica que o acesso em si é totalmente separado dos dados. Por exemplo, você pode manipular alguns dados e expô-los através de uma referência const. O acesso é somente leitura, mas os dados em si, pois todo o datam é mutável.

const apenas garante limitações de acesso, enquanto a imutabilidade (como em D, por exemplo) não implica realmente nenhuma maneira de alterar os dados em qualquer estágio da vida do objeto .

Agora, você pode simular a imutabilidade no C ++, certificando-se de que alguns dados não possam ser acessados ​​de outra maneira que não const e verifique se eles foram inicializados e não mais tocados. Mas isso não é uma garantia forte, pois linguagens como D oferecem quando você marca seus dados como imutáveis. A linguagem garante que não seja possível realizar nenhuma operação de modificação desses dados, enquanto em C ++ você ainda é potencialmente capaz de alterar os dados por meio da conversão e mutabilidade de const, se realmente necessário.

No final, não é o mesmo , pois não oferece as mesmas garantias.


3

Falando em JavaScript, as palavras-chave consteObject.freeze

constaplica-se a ligaçõesvariables . Ele cria uma ligação imutável, você não pode atribuir um novo valor a ela.

Object.freezetrabalha com valores de objetos. Torna um objeto imutável . Ou seja, você não pode alterar suas propriedades.


0

Em C ++ eles são os mesmos. Embora você possa alterar um constobjeto, se tiver sua localização na memória e a permissão do SO para gravar nessa memória.


1
Na verdade, esse é um argumento contra eles serem iguais: o C ++ simplesmente não tem suporte a palavras-chave ou idiomas imutáveis. E também, estou assumindo que o programador utiliza a linguagem de maneira sã: caso contrário, const também não tem absolutamente nenhum valor.
21412 K.Steff

1
@ K.Steff - talvez melhor dizer que não há imutável-ness extra no C ++ que não seja fornecido pela const
Martin Beckett

Absolutamente :) precisa
K.Steff

Em C ++, eles não são os mesmos. const é o nível de acesso "somente leitura", não significa que os dados sejam imutáveis. Você pode ignorá-lo em C ++, na maioria das vezes.
Klaim

0

Em C, C ++ e linguagens relacionadas, também há uma diferença entre um objeto sendo const e sua referência ou ponteiro para o objeto sendo uma referência constante.

Se você tentar modificar um objeto constante, terá um comportamento indefinido. (Você pode tentar modificar um objeto constante, por exemplo, pegando seu endereço, convertendo o endereço em um ponteiro não const e, em seguida, usando esse ponteiro não const para modificar o objeto).

O ponteiro constante ou referência, por outro lado, apenas informa ao compilador que você não pode usar esse ponteiro ou referência para modificar o objeto. Você pode converter o ponteiro ou referência e tentar modificar o objeto. Se o objeto em si fosse constante, coisas ruins acontecerão. Se o objeto não fosse realmente constante, ele mudaria. Obviamente, isso pode confundir os usuários do seu código e possivelmente causar bugs.

Em C, se você usar uma string literal como "Hello", os cinco caracteres e os zero bytes à direita serão realmente constantes, mas você obterá um ponteiro não-const. É uma péssima idéia usar esse ponteiro não-const para alterar o objeto.

Em C, você pode ter um ponteiro "const restring". Isso significa que o objeto apontado é temporariamente constante. Se o objeto for modificado por qualquer meio enquanto o ponteiro "const restring" estiver no escopo, você terá um comportamento indefinido. Isso é mais forte que um ponteiro const, o que apenas impede que você altere um objeto por esse ponteiro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.