/*************************************************************************** * Copyright (C) 2005 by Jeff Ferr * * root@sat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "jpointer.h" #include #include class C { public: static int x; int y; public: C() { y = ++x; std::cout << "\tcreate C " << y << std::endl; } virtual ~C() { std::cout << "\tdestrut C " << y << std::endl; } void MaybeThrowException() { if (rand() % 2 == 0) { throw "erro"; } } }; int C::x = 0; class D: public C { public: D():C() { std::cout << "\tcreate D " << y << std::endl; } virtual ~D() { std::cout << "\tdestruct D " << y << std::endl; } }; class E { public: jcommon::ptr child; public: E() { std::cout << "\tcreate E" << std::endl; } virtual ~E() { std::cout << "\tdestruct E" << std::endl; } }; void AutoDeleteLocalVariableTest() { std::cout << "init" << std::endl; jcommon::ptr c = new C(); jcommon::ptr d = new D(); //delete d; <--- not needed //delete c; <--- not needed std::cout << "end" << std::endl; } void AutoDeleteNonReferencedObjectTest() { std::cout << "allocate object" << std::endl; jcommon::ptr c = new C(); std::cout << "same pointer referencing another object" << std::endl; // the next line do not generate leak memory c = new C(); // delete c; <--- not needed std::cout << "end" << std::endl; } void AutoDeleteNonReferencedObjectWithInheritance() { // same as the previous test, but in this case use inhiretance std::cout << "allocate C" << std::endl; jcommon::ptr c = new C(); std::cout << "allocate D" << std::endl; jcommon::ptr d = new D(); std::cout << "c referencing D" << std::endl; c = d; // delete c; <--- not needed std::cout << "end" << std::endl; } jcommon::ptr createObject() { return new C(); } void ObjectReturnedByFunctionTest() { std::cout << "keep the object returned by function" << std::endl; jcommon::ptr r = createObject(); std::cout << "dont keep the object returned by function" << std::endl; createObject(); std::cout << "end" << std::endl; } void ThrowExceptionTest() { jcommon::ptr c; try { c = new C(); c->MaybeThrowException(); // delete c; <--- not needed std::cout << "dont throw exception" << std::endl; } catch (...) { // delete c; <--- not needed std::cout << "throw exception" << std::endl; } // Observacao: ao utilizar ponteiros normais, // o seguinte codigo gera vazamento de memoria // quando ocorre uma excecao //C *c = new C(); //c->talvezLanceExcecao(); //delete c; // Os SmartPointers so resolvem o problema // de gerenciamento de memoria. No caso de // outros tipos de recurso, tais como arquivo, // mutex etc, o programador deve garantir que // os mesmos serao liberados. Exemplo: //try { // mutex.lock() // --> chama metodo que pode lancar excecao // --> se deu tudo certo... // mutex.unlock() //} catch (...) { // mutex.unlock(); // --> trata a excecao ou lanca para outro metodo //} // } void CyclicReferenceTest() { // esse eh o unico caso em que o ptr nao funciona jcommon::ptr e1 = new E(); jcommon::ptr e2 = new E(); jcommon::ptr e3 = new E(); e1->child = e2; e2->child = e3; e3->child = e1; } int main() { srand(time(0)); std::cout << "------------------\n" << std::endl; std::cout << "teste: local variable\n" << std::endl; AutoDeleteLocalVariableTest(); std::cout << std::endl; std::cout << "------------------\n" << std::endl; std::cout << "teste: object not referenced\n" << std::endl; AutoDeleteNonReferencedObjectTest(); std::cout << std::endl; std::cout << "------------------\n" << std::endl; std::cout << "teste: object not referenced with inhiretance\n" << std::endl; AutoDeleteNonReferencedObjectWithInheritance(); std::cout << std::endl; std::cout << "------------------'n" << std::endl; std::cout << "teste: object returned by function\n" << std::endl; ObjectReturnedByFunctionTest(); std::cout << std::endl; std::cout << "------------------\n" << std::endl; std::cout << "teste: exception handling\n" << std::endl; ThrowExceptionTest(); std::cout << std::endl; std::cout << "------------------\n" << std::endl; std::cout << "teste: cyclic reference\n" << std::endl; CyclicReferenceTest(); std::cout << std::endl; std::cout << "------------------" << std::endl; return 0; }