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