Você está na página 1de 7

Trabalho Linguagem Logica de Programao II Conceitos Bsicos em C++

Aluno: Igor Alves de Sousa

Namespace Para comear, vamos falar dos recursos de entrada e sada da biblioteca iostream em C++, sendo que para isso preciso incluir o comando using namespace std. Este comando serve para definir um "espao de nomes", ou namespace. Um namespace permite a definio de estruturas, classes, funes e constantes, que estaro vinculadas a ele. Isso evita duplicidade como, por exemplo, outras implementaes com nomes semelhantes. Por definio, a linguagem C++ utiliza o namespace std para definir todas as funes da biblioteca padro. Se no utilizarmos o comando using..., ser necessrio especificar explicitamente o namespace utilizado.

Using namespace std; Observando esta linha, alguns tradicionais programadores em linguagem C, tm uma novidade: namespaces so espaos de nomes dentro do cdigo, eles funcionam, entre outras coisas, como um meio de evitar duplicao de nomes dentro de um projeto extenso, que geralmente contam com inmeros arquivos. O C++ usa os namespaces para organizar os diferentes nomes usados nos programas. Cada nome usado no ficheiro/arquivo biblioteca "standard iostream" faz parte do "namespace" chamado de std. O objeto de sada padro, cout, est definido dentro do "namespace" std, ele um objeto da classe "ostream" "output stream", para acess-lo temos que referenci-lo como "std::cout". Para evitar que tenhamos que informar "std::" todas as vezes que precisarmos usar os recursos deste "namespace", podemos informar que estamos usando-o dentro do arquivo atual, conforme vemos na linha declarada no incio deste tpico. O "namespace" permite que as variveis sejam localizadas em certas regies do cdigo. Declarar o "namespace std" permite que todos os objetos e funes da biblioteca "standard input-output" possam ser usados sem quaisquer qualificaes especficas, desta maneira, no mais necessrio o uso de "std::". Este um conceito avanado que podemos explorar mais, vamos deix-lo para depois. Entrada e sada (cin/cout) cout << "Hello world! Digite um nmero:\n"; (c+out) Podemos utilizar este objeto porque pusemos o header e o namespace std. As informaes sero direcionadas atravs do iostream, um subsistema de entrada e sada da biblioteca padro. O que este objeto nos permite enviar o que temos entre aspas para a sada (out), que o monitor neste caso. Quem j conhece a linguagem C, certamente est familiarizado com os streams da biblioteca padro, o stdin, o stdout e o stderr... A linguagem C++ implementa os mesmos dispositivos sob a forma de objetos. O cout envia dados para o "standard output device", que usualmente o monitor, a abstrao do elemento de sada padro observada na presena de um objeto que representa a sada fsica de dados para o meio externo.

Observa-se que temos o operador <<, neste caso podemos verificar mais uma das funcionalidades da linguagem, pois este operador usado para deslocamento de bits na sua funcionalidade padro, neste caso a sua funo foi substituda por outra, transferir os dados a sua direita para o "output stream" do seu lado esquerdo. O cout um objeto da biblioteca "standard C++" que tem como uma de suas funes imprimirem strings no "standard output" (que normalmente o/a ecr/tela). Da mesma forma que podemos formatar o texto enviado a sada padro na linguagem C, tambm pode faz-lo com os objetos do C++, por exemplo, se acrescentssemos "<< hex <<" entre uma varivel e a sada: cout<< hex << n; O resultado seria impresso em hexadecimal; Para entrada de dados temos: cin >> a; O que esta linha faz colocar o valor que foi digitado numa rea de memria que foi chamada de "a". Da mesma forma que o cout existe para sada de dados, temos outro objeto para entrada atravs do teclado, este objeto chamado de Console IN - cin, seguindo a mesma analogia. Observe que o operador >> usado para dar ideia de que os dados esto vindo do cin para a varivel "a". cout << "Voc digitou o nmero: " << a << "\n"; Aqui voltamos a utilizar o objeto cout primeiro para imprimir no/na ecr/tela a frase "Voc digitou o nmero: ", depois vai buscar o valor que est naquela rea de memria a que chamamos de "a" e por fim coloca o fim de linha atravs de "\n", em C++ podemos usar um finalizador de linha chamado endl, o uso do mesmo mais eficiente pois descarrega os dados do stream logo aps a finalizao da linha. Operador Delete Memory Leak O tempo de vida de uma varivel criada dinamicamente o tempo de execuo do programa. Se um ponteiro aponta para uma varivel dinmica e fica out of scope, j no conseguiremos aceder a essa memria criada dinamicamente. Fica indisponvel. A isso se chama Memory Leak Explicando: se alocamos memria dinamicamente dentro de uma funo usando um ponteiro local, quando a funo termina, o ponteiro ser destrudo, mas a memria mantm-se. Assim j no teramos maneira de chamar essa memria porque ela no tem nome! Apenas tnhamos o endereo que estava no ponteiro. Portanto, se realmente no necessitamos mais dos dados que esto nessa memria dinmica, em vez de eles estarem a ocupar espao vamos apag-los! Necessitamos de libertar essa memria atravs do operador delete este operador entrega ao sistema operativo a memoria reservada dinamicamente. A sintaxe delete [] iPtr; Este delete operator no apaga o pointer, mas sim a memria onde o ponteiro aponta

dynamic memory allocation funciona porque a memria no reservada no momento da compilao, mas antes na execuo. Em vez de ser no STACK (compilao) a memria reservada no HEAP (execuo). O heap uma parte da memria que usada como memria temporria. Pergunta: onde que fica situado o Heap? Vamos explicar melhor todo este processo: pois isto tem de entrar na cabea! void myfunction () { int *pt; int av; pt = new int(1024); .... .... //No delete } int main() { while (some condition exists) // Pseudo-code { myfunction(); } exit 0; } quando a funo myfunction chamada a varivel av criada no stack e quando a funo acaba a variavel retirada do stack. O mesmo acontece com o ponteiro pt, ele uma varivel local, ou seja, quando a funo acaba o ponteiro tambm termina e retirado do stack. Porm o objeto alocado dinamicamente ainda existe. E agora no conseguimos apagar esse objeto por que ele no tem nome e a nica maneira que tnhamos para saber onde ele estava era atravs do ponteiro que terminou quando termina a funo, pois ele local. Ento medida que o programa continua a operar mais e mais memria ser perdida do Heap (free store). Se o programa continuar o tempo suficiente, deixaremos de ter memria disponvel e o programa deixar de operar. Regras e recomendaes 16 - Alocao de memria Regras:

50: No use malloc, realloc ou free. 51: Sempre codifique colchetes vazios ([]) para delete quando desalocar matrizes

Recomendaes:

57: Evite dados globais, tanto quanto possvel. 58: No aloque memria esperando que alguma outra funo v desaloca-la mais tarde 59: Sempre atribua um novo valor a um pointer que aponta para uma rea de memria desalocada

Em C++, os dados podem ser alocados estaticamente, dinamicamente na stack, ou dinamicamente no heap. H trs categorias de dados estticos: dados globais, dados globais da classe e dados locais estticos para uma funo. Em C, malloc, realloc e free so usados para alocar dinamicamente memria noheap. Isso pode levar a conflitos com o uso dos operadores new e delete em C++. perigoso:

Invocar delete para um pointer obtido via malloc/realloc Invocar malloc/realloc para objetos que tenham construtores Invocar free para qualquer memria alocada via new

Portanto, evite tanto quanto possvel o uso de malloc, realloc ou free. Se uma matriz a de um tipo T for alocada, importante invocar delete do modo correto. Escrever apenas delete a; resultar na invocao do destrutor exclusivamente para o primeiro objeto do tipo T. Escrever delete[m] a; onde m um inteiro maior que o nmero de objetos alocados anteriormente, invocar o destrutor para memria que no representa objetos do tipo T. A maneira mais fcil de desalocar uma matriz corretamente escrever delete [] a; porque assim o destrutor ser invocado para os objetos que foram alocados anteriormente. Dados estticos podem causar numerosos problemas. Em um ambiente em que parallel treads so executadas simultaneamente, o comportamento do programa pode tornar-se imprevisvel, j que funes que tm dados estticos no so reentrantes. Uma diferena entre o ANSI-C e o C++ o modo de declarar constantes. Se uma varivel declarada como constante em ANSI-C ela recebe a classe de armazenamento extern(global). Em C++, entretanto, ela normalmente recebe a classe de armazenamento static(local). Isso significa que uma nova instncia do objeto constante ser criada a cada vez que um arquivo incluir um arquivo que contenha uma declarao do objeto, a menos que a varivel seja declarada explicitamente como extern no arquivo include. Uma declarao extern em C++ no significa que a varivel est inicializada; deve haver uma inicializao para a varivel no arquivo que a define. Constantes estticas que so definidas dentro da classe so sempre externas e devem, sempre, ser definidas separadamente. permitido, s vezes, alocar memria para um objeto usando new, esperando que outra funo v desaloc-la. A propsito, uma funo pode alocar memria para um objeto pass-lo para o usurio da funo como valor de retorno. No h garantia de que o usurio da funo v se lembrar de desalocar a memria, e essa abordagem torna a interface com a funo consideravelmente mais complexa. Pointers que apontam para memria desalocada devem conter 0 (zero) para prevenir o acesso memria j liberada. Quando vrios pointers apontam para a mesma rea de memria pode-se ter problemas difceis de resolver. Excees regra:

50: Sem excees 51: Sem excees

Exemplo 64: As maneiras correta e errada de invocar delete para uma matriz com destrutores

int n = 7; T* myT = new T[n]; // T is a type with defined constructors and destructors // ... delete myT; // No! Destructor only called for first object in array a delete [10] myT; // No! Destructor called on memory out of bounds in array a delete [] myT; // OK, and always safe! Exemplo 65: Gerenciamento de memoria temerrio String myFunc( const char* myArgument ) { String* temp = new String( myArgument ); return *temp; // temp is never deallocated and the user of myFunc cannot deallocate // because a temporary copy of that instance is returned. } Alocando memria dinmica em C++ usando o operador new

Em algumas situaes precisamos alocar memria dinamicamente. Em C++ isso feito com o auxlio do operador new. Este operador permite alocar uma determinada quantidade de bytes, alinhados de forma a representar o objeto para o qual queremos reservar memria. Veja um exemplo de cdigo no qual alocamos memria dinmica para uma varivel do tipo int:

#include <iostream> using namespace std; int main(int argc, char *argv[]){ // aloca memria para um objeto do tipo int int *ponteiro = new int; // vamos definir o valor para o objeto recm-alocado *ponteiro = 20; // vamos exibir seu valor cout << *ponteiro << endl; // vamos liberar a memria delete ponteiro; system("PAUSE"); // pausa o programa return EXIT_SUCCESS; } Note que aqui a memria foi alocada e guardada em um ponteiro. Veja tambm o uso do operador delete para liberar a memria alocada. Isso evita os vazamentos de memria to frequentes em aplicaes que lidam com a memria dinmica. claro que este no o exemplo mais prtico. Qual a vantagem de se alocar memria para um int? Declarar uma varivel teria sido mais eficiente. A alocao de memria dinmica mais til quando estamos lidando com objetos mais

complexos que os tipos bsicos. Alguns exemplos envolvem a criao de objetos de classes, matrizes, estruturas de dados, etc. Veja um exemplo no qual temos uma declarao de uma classe chamada Cliente e em seguida alocamos memria para uma instncia desta classe:

#include <iostream> #include <string> using namespace std; // declarao da classe Cliente class Cliente{ public: Cliente(); string obterNome(); void definirNome(string); private: string nome; }; // implementao dos mtodos da classe Cliente::Cliente(){} // construtor vazio // obtm o nome do cliente string Cliente::obterNome(){ return this->nome; } // define o nome do cliente void Cliente::definirNome(string nome){ this->nome = nome; } int main(int argc, char *argv[]){ // aloca memria para um objeto da classe Cliente Cliente *c = new Cliente(); // vamos definir o nome do cliente c->definirNome("Osmar J. Silva"); // vamos exibir o nome do cliente cout << c->obterNome() << endl; // vamos liberar a memria usada delete c; system("PAUSE"); // pausa o programa return EXIT_SUCCESS; }

Você também pode gostar