Pesquisei sobre esse livro e procurei nele o exemplo que você citou. Vi que no main()
tem esta linha:
double horas = obterHoras(dias);
Então, apesar de obterHoras()
retornar uma referência, o valor desta referência está sendo copiado para fora da função e sendo armazenado na variável horas
. Por este motivo o programa funciona como planejado, não tá errado, tecnicamente falando.
Para ver melhor o que está acontecendo, experimente este código:
int main() {
int x = 123;
int& r = x;
int y = r;
std::cout << x << " " << y << "\n"; // 123 123
y = 456;
std::cout << x << " " << y; // 123 456
}
O trecho acima serve pra mostrar como os valores de x
e y
são independentes entre si.
O que achei estranho é que antes do trecho que você mostrou tá escrito assim:
Uma das principais motivações para fazer isso é quando a quantidade de informação a ser retornada é grande e, portanto, torna-se muito mais eficiente uma referência em vez de retornar uma cópia.
Mas o exemplo dado não ilustra nem de longe esta “eficiência” e, na verdade, pode até causar bugs chatinhos.
Acredito que o verdadeiro valor de se retornar por referência vai ficar mais claro quando você estiver trabalhando com classes. Imagine que você tem uma classe Person
e quer poder acessar o valor de um atributo chamado name
. Sem referência ficaria assim:
class Person {
std::string name;
public:
Person(std::string n): name{n} {}
std::string getName() {
return name;
}
};
E para usá-la:
int main() {
Person p{"Wellington"};
std::cout << p.getName() << std::endl;
}
Mas isto acrescenta vários problemas. Logo no construtor, eu crio uma string
e copio está string
para dentro da classe. Na função getName()
eu também retorno uma cópia da mesma string e estas cópias são desnecessárias uma vez que eu só quero ler o valor e não modificá-lo. Então, para melhorar eu poderia usar referências:
class Person {
std::string name;
public:
Person(std::string & n): name{n} {}
std::string & getName() {
return name;
}
};
Isso já nos ajuda com relação as cópias desnecessárias das strings, mas acrescenta uma falha séria de encapsulamento. É esperado que a variável name
seja privada e que o lado de fora da classe não possa acessá-la e muito menos alterar seu valor, porém considere o seguinte código:
int main() {
Person p{"Wellington"};
std::cout << p.getName() << std::endl; // Wellington
p.getName() = "Juliano";
std::cout << p.getName() << std::endl; // Juliano
return 0;
}
Percebeu? Este é o tipo de perigo que linguagens como Java não nos deixa correr (claro que em Java teremos que continuar tomando cuidado com encapsulamento, mas já são outros cuidados). Para resolver é simples, basta usarmos referências constantes, asssim:
Person(const std::string & n): name{n} {}
const std::string & getName() {
return name;
}
A palavra-chave const
faz toda a diferença aqui e vai fazer com que o compilador gere um erro quando chegar em:
p.getName() = "Juliano";
Não sei em que ponto do estudo vc já está, mas se eu mostrei alguma coisa que vc ainda não aprendeu, não se preocupe, os exemplos servem apenas para dar uma prévia do que está por vir. C++ é bastante poderosa e nos dá controle máximo sobre nosso programa, estude com calma e continue não aceitando tudo o que vê em livros, apostilas, videos ou em respostas em fóruns, questione tudo. Flw.