Pergunto-me que méritos possíveis o copy-on-write tem? Naturalmente, não espero opiniões pessoais, mas cenários práticos do mundo real em que pode ser técnica e praticamente benéfica de maneira tangível. Por tangível, quero dizer algo mais do que poupar a digitação de um &
personagem.
Para esclarecer, essa pergunta está no contexto de tipos de dados, em que a construção de atribuição ou cópia cria uma cópia superficial implícita, mas as modificações nela criam uma cópia profunda implícita e aplicam as alterações a ela, em vez do objeto original.
A razão pela qual estou perguntando é que não consigo encontrar nenhum mérito de ter a COW como um comportamento implícito padrão. Eu uso o Qt, que implementou o COW para muitos tipos de dados, praticamente todos os quais possuem algum armazenamento alocado dinamicamente subjacente. Mas como isso realmente beneficia o usuário?
Um exemplo:
QString s("some text");
QString s1 = s; // now both s and s1 internally use the same resource
qDebug() << s1; // const operation, nothing changes
s1[o] = z; // s1 "detaches" from s, allocates new storage and modifies first character
// s is still "some text"
O que ganhamos usando o COW neste exemplo?
Se tudo o que pretendemos fazer é usar operações const, s1
é redundante e pode ser usado s
.
Se pretendemos alterar o valor, o COW apenas atrasa a cópia do recurso até a primeira operação não const, ao custo (ainda que mínimo) de incrementar a contagem de ref para o compartilhamento implícito e a desanexação do armazenamento compartilhado. Parece que toda a sobrecarga envolvida na COW é inútil.
Não é muito diferente no contexto da passagem de parâmetros - se você não pretende modificar o valor, passe como referência const; se quiser modificar, faça uma cópia implícita e profunda se não quiser modificar o objeto original ou passe por referência, se desejar modificá-lo. Novamente, o COW parece uma sobrecarga desnecessária que não alcança nada e apenas adiciona uma limitação de que você não pode modificar o valor original, mesmo que queira, pois qualquer alteração será destacada do objeto original.
Portanto, dependendo se você conhece a COW ou não o conhece, pode resultar em código com intenção obscura e sobrecarga desnecessária, ou comportamento completamente confuso que não corresponde às expectativas e deixa você coçando a cabeça.
Para mim, parece que existem soluções mais eficientes e legíveis, se você deseja evitar uma cópia profunda desnecessária ou se pretende fazer uma. Então, onde está o benefício prático da vaca? Suponho que deve haver algum benefício, pois é usado em uma estrutura tão popular e poderosa.
Além disso, pelo que li, o COW agora é explicitamente proibido na biblioteca padrão do C ++. Não sei se os truques que vejo nele têm algo a ver com isso, mas, de qualquer forma, deve haver uma razão para isso.
[]
operador. Portanto, o COW permite um design ruim - que não parece muito benéfico :) O ponto do último parágrafo parece válido, mas eu próprio não sou um grande fã de comportamento implícito - as pessoas tendem a considerá-lo um dado adquirido e depois têm é difícil descobrir por que o código não funciona como o esperado e fica pensando até descobrirem o que está oculto por trás do comportamento implícito.