De Objective Caml para C e C++/Construção de tipos: diferenças entre revisões

[edição não verificada][edição não verificada]
Conteúdo apagado Conteúdo adicionado
Linha 436:
===Tipos referências===
 
====Introdução ao conceito====
A linguagem Objective Caml possui um conceito de referência que pode ser relacionado com as variáveis e os ponteiros das linguagens C e C++. A linguagem C++ possui um outro conceito, que também é chamado de referência, mas que é diferente. Para evitar qualquer confusão, passaremos a chamá-las de "referências C++". Vale destacar que o conceito de referência C++ não existe na linguagem C.
 
Uma referência C++ permite declarar um sinônimo para um outro objeto. SãoSe principalmente<tt>T</tt> usadosrepresenta paraalgum passartipo, parâmetrosentão por<tt>T &</tt> representa uma referência, opara queaquele permitetipo. passarObserve umentão objetoque parao asímbolo funçãotem chamada.um Lembramosterceiro quesentido normalmente,(além emde Cconjunção ebit C++,a osbit argumentose sãode passadosoperador porde valorendereço), ouque sejaé osde valoresconstruir sãoum copiadostipo parareferência. instanciarA ossintaxe parâmetrosé formais.assim:
tipo & nome = lvalue;
onde <tt>tipo</tt> é uma expressão de tipo, <tt>lvalue</tt> é alguma expressão que representa alguma <i>lvalue</i>, e <tt>nome</tt> é um nome que será sinônima daquela <i>lvalue</tt>. Essa associação permanecerá até que termine o escopo de <tt>nome</tt>. Vejamos agora um exemplo:
#include <cstdio>
int main ()
{
int a = 1;
int b = 2;
int & r = a;
printf ("1. a = %i, b = %i, r = %i\n", a, b, r);
r = b;
printf ("2. a = %i, b = %i, r = %i\n", a, b, r);
printf ("3. &a = %p, &b = %b, &r = %p\n", &a, &b, &r);
}
A execução desse código resultará na seguinte impressão na saída padrão:
1. a = 1, b = 2, r = 1
2. a = 2, b = 2, r = 2
3. &a = 0xbffff8dc, &b = 0xbffff8e0, &r = 0xbffff8dc
A explicação é a seguinte. O programa possui três variáveis: <tt>a</tt> e <tt>b</tt>, ambas inteiras, e <tt>r</tt> uma referência para a variável <tt>a</tt>. Assim, na seqüência, <tt>r</tt> é um sinônimo de <tt>a</tt>. Na impressão <tt>1</tt>, o valor de <tt>r</tt> é então o mesmo que o de <tt>a</tt>. Em seguida, <tt>r</tt> é atribuída <tt>b</tt>. Como <tt>r</tt> é uma referência para <tt>a</tt>, isso significa o valor de <tt>b</tt> (ou seja <math>2</math>) é atribuído <tt>r</tt>, logo a <tt>a</tt>. Na impressão <tt>2</tt>, aparece então que tanto <tt>a</tt> como <tt>r</tt> tem o mesmo valor que é <math>2</math>. Finalmente, a impressão <tt>3</tt>, que mostra os endereços das três variáveis comprova que, efetivamente, o compilador associou a <tt>a</tt> e a <tt>r</tt> o mesmo endereço.
 
====Discussão====
 
O leitor sagaz pode perguntar-se então para quem servem as referências, já que elas parecem apenas introduzir complexidade: criar novos nomes para objetos já existentes só pode aumentar confusão! Na prática, as referências são principalmente usadas para permitir programar com facilidade um mecanismo de funções com '''parâmetros por referência''', que permite passar um objeto para a função chamada. Esse mecanismo, presente em linguagens clássicas como Pascal, é ausente das linguagens C e Objective Caml, onde deve ser programado através de ponteiros (em C) e de referências (em OCaml).
 
Lembramos que, normalmente, em C e C++, os argumentos são passados por valor, ou seja os valores são copiados para instanciar os parâmetros formais. O fato de termos um parâmetro por referência faz com que é o próprio argumento que é recebido pela função chamada, e não uma cópia do valor desse argumento.
 
O exemplo seguinte mostra um aplicação clássica de passagem por referência:
#include <cstdio>
void swap (int & a, int & b)
{
Linha 447 ⟶ 474:
b = tmp;
}
int main ()
{
int a = 1;
int b = 2;
printf("antes: a = %i, b = %i.\n", a, b);
swap (a, b);
printf("depois: a = %i, b = %i.\n", a, b);
}
A execução desse programa resultará na seguinte impressão na saída padrão:
antes: a = 1, b = 2.
depois: a = 2, b = 1.
 
Para fins de comparação, um programa equivalente em C, com ponteiros e sem referências C++, seria:
#include <stdio.h>
void swap (int * a, int * b)
{
int tmp;
tmp = * a;
* a = * b;
& b = tmp;
}
int main ()
{
int a = 1;
int b = 2;
printf("antes: a = %i, b = %i.\n", a, b);
swap (& a, & b);
printf("depois: a = %i, b = %i.\n", a, b);
}
 
====Inicialização de referências====
 
{{Code:Error
|Quando não é um parâmetro de função, uma referência deve ser inicializada na sua declaração. Se omitirmos essa inicialização, então o compilador emitirá uma mensagem de erro.
|<pre>
#include <cstdio>
int main ()
{
int a = 1;
int b = 2;
int & r;
printf("a = %i, b = %i, r = %i.\n", a, b, r);
}
</pre>
|
A compilação desse código não foi bem-sucedida, e imprimiu a seguinte mensagem na tela:
prog.cpp: In function 'int main()':
prog.cpp:6: error: 'r' declared as reference but not initialized
}}
 
===Tipos uniões===