Passei por esta página, mas não sou capaz de entender o motivo. Lá é mencionado que
"é mais sensato não retornar nenhum valor e exigir que os clientes usem front () para inspecionar o valor na frente da fila"
Mas a inspeção de um elemento de front () também exigia que esse elemento fosse copiado em lvalue. Por exemplo, neste segmento de código
std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);
/ * aqui temporário será criado no RHS que será atribuído ao resultado e, se retornos por referência, o resultado será invalidado após a operação pop * /
result = myqueue.front(); //result.
std::cout << ' ' << result;
myqueue.pop();
na quinta linha, o objeto cout cria primeiro uma cópia do myqueue.front () e depois atribui isso ao resultado. Então, qual é a diferença, a função pop poderia ter feito a mesma coisa.
void std::queue::pop();
).front()
também requer que esse elemento seja copiado em lvalue" - não, não é.front
retorna uma referência, não um valor. Você pode inspecionar o valor a que se refere sem copiá-lo.pop()
. Se você usarstd::queue<T, std::list<T>>
, não há nenhuma preocupação sobre a referência fornecidafront()
ser invalidada por apush()
. Mas você deve conhecer seu padrão de uso e documentar suas restrições.Respostas:
Poderia realmente ter feito a mesma coisa. O motivo disso não ocorreu é porque um pop que retornou o elemento popped não é seguro na presença de exceções (tendo que retornar por valor e, assim, criar uma cópia).
Considere este cenário (com uma implementação pop ingênua / inventada, para ilustrar meu argumento):
Se o construtor de cópias de T lançar no retorno, você já alterou o estado da fila (
top_position
na minha implementação ingênua) e o elemento será removido da fila (e não retornado). Para todas as intenções e propósitos (não importa como você captura a exceção no código do cliente), o elemento na parte superior da fila é perdido.Essa implementação também é ineficiente no caso em que você não precisa do valor pop-up (isto é, cria uma cópia do elemento que ninguém usará).
Isso pode ser implementado com segurança e eficiência, com duas operações separadas (
void pop
econst T& front()
).fonte
pop
? isso é bastante contra-intuitivo. Poderia ser nomeadodrop
e, então, fica claro para todos que ele não aparece o elemento, mas o solta ...pop
não retornar nada. Veja, por exemplo, na wikipedia .A página à qual você vinculou responde à sua pergunta.
Para citar toda a seção relevante:
O C ++ é projetado com eficiência em mente, sobre o número de linhas de código que o programador precisa escrever.
fonte
pop
qual retorna um valor.pop não pode retornar uma referência ao valor removido, pois está sendo removido da estrutura de dados; portanto, a que referência deve se referir? Pode retornar por valor, mas e se o resultado de pop não for armazenado em nenhum lugar? Então se perde tempo copiando o valor desnecessariamente.
fonte
pop
retornos e o ato de retornar podem resultar em uma exceção. Obviamente, seria necessário remover o elemento antes de devolvê-lo e, se algo jogar, o elemento poderá ser irrevogavelmente perdido.value_type
possui um construtor de movimentação de nothrow, mas a interface da fila seria diferente dependendo do tipo de objeto armazenado nela, o que não seria útil.Com a implementação atual, isso é válido:
Se pop retornasse uma referência, assim:
Em seguida, o código a seguir pode falhar, pois a referência não é mais válida:
Por outro lado, se ele retornasse um valor diretamente:
Então você precisaria fazer uma cópia para esse código funcionar, o que é menos eficiente:
fonte
A partir do C ++ 11, seria possível arquivar o comportamento desejado usando a semântica de movimentação. Like
pop_and_move
. Portanto, o construtor de cópias não será chamado e o desempenho dependerá apenas do construtor de movimentação.fonte
pop
exceção segura.Você pode fazer isso totalmente:
Ou, se você quiser o valor em uma variável, use uma referência:
Além disso: o termo 'mais sensível' é uma forma subjetiva de 'examinamos os padrões de uso e descobrimos mais necessidade de uma divisão'. (Tenha certeza: a linguagem C ++ não está evoluindo levemente ...)
fonte
Eu acho que a melhor solução seria adicionar algo como
onde value receberá o valor popped.
A vantagem é que ele pode ser implementado usando um operador de atribuição de movimento, enquanto usar front + pop fará uma cópia.
fonte