Hi Rene, Rene Brun <Rene.Brun@cern.ch> wrote concerning Re: [ROOT] Seg.Violation on return TGraph [Wed, 12 Mar 2003 19:57:35 +0100 (MET)] ---------------------------------------------------------------------- > Hi Sven, > > What you do is illegal in C++ Erh, no it's not illegal (that would make the function `int foo(int x) { int y = x; return y;}' illegal too :-) ... > (and anyhow very inefficient). ... but highly inefficient - yes. > When leaving your makegraph function, the object is deleted. > when leaving the scope ! No it isn't - it's copied out (via the copy constructor) before being deallocated from the stack, passing the copy on the return stack! Not very cool, but not illegal at all. > You can do as shown below The example you gave is much more efficient of course, but try also this piece of code: #include <iostream> class foo { private: int _foo; public: foo(int f) : _foo(f) { std::cout << "- " << _foo << ": foo::foo(int)" << std::endl; } ~foo() { std::cout << "- " << _foo << ": foo::~foo" << std::endl; } foo(const foo& o) : _foo(o._foo) { std::cout << "- " << _foo << ": foo::foo(const foo&)" << std::endl; } }; foo create_foo1(int x) { std::cout << "+ 1: plain object" << std::endl; foo f(x); return f; } foo& create_foo2(int x) { std::cout << "+ 2: reference" << std::endl; foo f(x); return f; } foo* create_foo3(int x) { std::cout << "+ 3: pointer" << std::endl; foo* f = new foo(x); return f; } foo create_foo4(int x) { std::cout << "+ 4: direct object" << std::endl; return foo(x); } int main(int argc, char** argv) { foo f1 = create_foo1(1); std::cout << "==> Notice the extra copy above?" << std::endl; foo& f2 = create_foo2(2); std::cout << "==> Notice the destruction but no copy above?" << std::endl; foo* f3 = create_foo3(3); std::cout << "==> Notice there's no copy/deletion at all?" << std::endl; foo f4 = create_foo4(4); std::cout << "==> Notice the lack of copy here too?" << std::endl; std::cout << "==> At end of program 1 & 4 is free'd - 2 is not" << std::endl; return 0; } In particular notice the 3rd case, were the function construct the object on the return stack, rather than as a temporary. I haven't checked with the ISO/IEC standard whether this the correct _and_ guarantied behaviour, but it compiles and works the same with both GCC 3.0.4, Intel's C++ compiler version 7.0, Compaq C++ v6.3, and Sun WorkShop 4.2 so I'd say there's a pretty good chance it's right. Now, whether other compilers (and linkers) behave the same - I really have no idea (my guess is at least one will behave differently, even if the behaviour is dictated by the ISO/IEC standard - guess which one :-) I'd like to direct your attention to Andrei Alexandrescu excellent article [1] on how to avoid temporary objects. Also his book is quite good too. Yours, ___ | Christian Holm Christensen |_| | ------------------------------------------------------------- | | Address: Sankt Hansgade 23, 1. th. Phone: (+45) 35 35 96 91 _| DK-2200 Copenhagen N Cell: (+45) 24 61 85 91 _| Denmark Office: (+45) 353 25 305 ____| Email: cholm@nbi.dk Web: www.nbi.dk/~cholm | | [1] http://www.cuj.com/experts/2102/alexandr.htm?topic=experts
This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:10 MET