paulo1205
(usa Ubuntu)
Enviado em 16/01/2016 - 04:42h
Porque tanto o ambiente de execução quanto o sistema operacional trabalham com buffers.
Buffers são regiões de memória usadas para guardar temporariamente dados recebidos de uma das pontas do canal de comunicação antes de entregá-los à outra ponta. Geralmente o emprego de buffers ajuda a diminuir a quantidade total de operações ao longo do canal como um todo, e isso é especialmente valioso quando uma das pontas tem velocidade muito diferente da da outra ponta.
No seu caso, provavelmente está acontecendo o seguinte:
1) A primeira operação de leitura do seu programa tenta consumir dados do buffer de leitura associado a
std::cin, mas o encontra vazio.
2) De modo a poder satisfazer a solicitação de leitura solicitada pelo programa, o ambiente de execução é obrigado a pedir dados ao sistema operacional, e ele o faz pedindo uma quantidade de bytes suficiente para encher todo o buffer logo de uma vez (tipicamente 1024, 4096 ou 8192 bytes, mas isso pode ser alterado).
3) O sistema operacional tenta obter os dados solicitados a partir da fonte de dados. Poderia ser um arquivo, um fluxo de comunicação via rede, uma porta serial ou outra fonte de dados qualquer, e cada uma potencialmente teria um tipo de tratamento distinto das demais, mas provavelmente todos eles com um ou mais tipos de buffers e cache. No seu caso, você está lendo de um terminal (físico, como o console, ou virtual, como uma janela de terminal dentro do ambiente gráfico ou via conexão de rede).
4) Tipicamente o sistema operacional trata o terminal como um dispositivo orientado a linha (isso pode ser mudado, mas o seu programa não faz qualquer mudança nesse sentido). Isso significa que o sistema só vai entregar os dados obtidos quando encontrar uma marca de fim de linha, mesmo que a marca de fim de linha só ocorra após a quantidade de caracteres solicitada pelo ambiente de execução. Até que apareça a marca de fim de linha, os caracteres obtidos são colocados no buffer do
device driver que trata o terminal (a não ser que ocorra alguma situação que interrompa o fluxo de dados, tal como fim de comunicação ou erro; nesse caso o sistema entrega os dados imediatamente).
5) Quando o sistema operacional entrega os dados ao ambiente de execução, tais dados não são diretamente repassados ao cliente, mas são postos no buffer do ambiente de execução.
6) Nesse momento é que o ambiente de operação vai tomar as providências para entregar ao programa os dados solicitados. No seu caso, essa entrega se dá através da transferência de caracteres presentes no buffer para o interior da sua string, de acordo com os critérios de
std::operator>>(istream &, string &), que é pular espaços em branco no início do buffer e transferir todos os caracteres não-espaço até a ocorrência do próximo espaço em branco, sendo que:
6.a) se os caracteres do buffer acabarem antes do próximo espaço em branco e o sistema operacional não tiver indicado fim do fluxo de dados, o ambiente de execução vai solicitar mais dados ao sistema operacional; e
6.b) não necessariamente a nova solicitação ao sistema operacional vai provocar a leitura de mais dados do teclado, pois pode haver dados no buffer do
device driver, remanescentes da leitura anterior que tenha consumido menos caracteres do que a quantidade digitada até a marca de fim de linha.
7) O resultado da operação de leitura é refletido em
std::cin, e o valor de
std::cin é convertido para booleano e testado como condição do comando de repetição
while no seu programa. Se for verdadeiro, uma nova iteração do loop prossegue a partir do passo (6); caso contrário, o loop termina.