Thread: Is it ALWAYS safe to return temporary variables ?

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    4

    Is it ALWAYS safe to return temporary variables ?

    Is it always safe to return temporary stack variables from a function as long as you don't return a reference or a pointer ? So is this always gauranteed to be safe, on all platforms/compilers/targets ? The compiler is never going to generate ASM that uses the location of testA in an unsafe manner ? (e.g. a location on the stack that is trashed when getA() returns)

    Code:
     
    MyBigClass getA()
    {
    .
    .
    	MyBigClass testA;
    	testA.DoStuff(x,y,z);
    
    	return testA;
    }
    
    
    
    int main(int argc, char* argv[])
    {
    .
    .
    	MyBigClass a0=getA();
    .
    .
    	a0.Dump();
    }
    I have always assumed it was (that it would always return a copy of testA no matter what) but someone just pointed this out at a potential bug. I'm not sure whether to beleive him :-)

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    There is nothing wrong with the above. You can return a copy of an object as long as that object has an implicit or explicit copy constructor
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >but someone just pointed this out at a potential bug.
    Who told you that, and what proof do they have?
    My best code is written with the delete key.

  4. #4
    Registered User
    Join Date
    Nov 2005
    Posts
    4
    Quote Originally Posted by Prelude
    >but someone just pointed this out at a potential bug.
    Who told you that, and what proof do they have?
    They don't... But then I don't have any proof to the contrary :-) I've alway ASSUMED that this was safe (that compiler was gauranted to copy the returned variable before the stack was popped), and its never failed for me, but I never really thought about it. He recon'ed it would usually be the case if the variable was small, but if it was big the generate ASM could potentially pass the reference to the location on the stack (which would *usually* work, but could conceiably get corrupted before it was used).

    The point is I know it usually (i.e. in all the cases I've ever done it) works, but is it GAURANTEED to work no matter what compiler and what H/W.

  5. #5
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by Mario F.
    There is nothing wrong with the above. You can return a copy of an object as long as that object has an implicit or explicit copy constructor
    Copy constructor and assignment operator both, as sometimes it can't use the copy constructor (e.g. if the variable already existed, it will use the assignment operator).

    Anyhow, nobody can say what happens on all compilers, but all compilers *following C++ standards* allow this.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  6. #6
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >but is it GAURANTEED to work no matter what compiler and what H/W.
    For a conforming compiler, absolutely. Unfortunately, we can't make blanket claims about non-conforming compilers. However, these semantics have been in place since before C, so any compiler that fails to make that guarantee while claiming to implement C++ is severely broken.
    My best code is written with the delete key.

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    There is one situation, and that is when the local object itself holds a reference to another local object and its copy constructor does not copy that object. In that case, the same caveats as with returning temporaries apply.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Mario F.
    There is nothing wrong with the above. You can return a copy of an object as long as that object has an implicit or explicit copy constructor
    That's not necessarily true. The copy constructor (and assignment operator) need to provide the comment semantics, regardless of whether they are implicit (eg compiler generated) or explicit (eg programmer generated).

    As CorndBee alluded, one case where this isn't necessarily true is if the class type contains a pointer or reference type. In practice, the implicitly generated constructor may not do this correctly (as it effectively does a bitwise copy of the value of pointers and references, which may not make sense for the class). If the programmer forgets to explicitly provide a copy constructor and/or assignment operator for the class in this case, returning an object of that type from a function (which logically invokes the copy constructor) or assigning the value to a variable (which logically invokes the assignment operator or copy constructor) can yield undefined or other spurious behaviours.

    For example, this causes both a memory leak and undefined behaviour as main() returns.
    Code:
    #include <iostream>
    class X
    {
        int *x;
       
        public:
            X() : x (new int) {};
            ~X() {delete x;};
            void set(int y) {*x = y;};
            void print() const {std::cout << *x << '\n';};
    }
    
    int main()
    {
         X a;
         X b = a;    // this invokes copy constructor
    
         //  Problem now  ....   a.x and b.x point at the same integer as the
         //    compiler generated copy constructor does a bitwise copy of pointers
    
         a.set(5);
         b.set(10);
         a.print();    // will print a value of 10, not 5
         b.print()     // will print a value of 10
         
         //   as main() returns destructors invoked.
         //    a.x will be deleted twice =>undefined behaviour
         //    the original value of b.x (as created by b's constructor) will not
         //      be deleted by X's destructor
       
    }
    The above ignores compiler optimisation. Things get a little more complicated, as compilers are allowed to -- but not required to -- eliminate some calls of constructors in some instances involving temporaries (and returning a value from a function is once such instance => the return value optimisation). Such things virtually guarantee that the code above will function differently between compilers and even compiler/optimiser settings for a particular compiler (even if we ignore the presence of undefined behaviour as main() returns).
    Last edited by grumpy; 09-01-2006 at 05:05 PM.

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >That's not necessarily true.
    I think you missed this part of Mario's post:
    >or explicit copy constructor

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by swoopy
    >That's not necessarily true.
    I think you missed this part of Mario's post:
    >or explicit copy constructor
    No I did not. I just used an example with an implicitly generated copy constructor.

    Having an explicit copy constructor is not the same thing as making that copy constructor behave correctly for all usage patterns. There is no way to force a programmer (other than embarrassment and other non-technical means) to write a copy constructor that does what the user of the class expects.
    Last edited by grumpy; 09-01-2006 at 06:03 PM.

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    As I said on Gamedev:

    The claim that the compiler is not GAURANTEED to pass a copy of the return value, is essentially FALSE. As far as the compiler is concerned this is ALWAYS okay. It may not necessarily copy the return value if it performs NRVO, but the effect is the same and is always legal.

    The only issue comes from bugs that the programmer of the class [being copied on return] has made.
    For example not following the http://cpp.codenewbie.com/articles/c...ee-Page_1.html "rule of three" as necessary.
    Or if the class should not be copyable, but it does not contain a private copy-constructor preventing this.

    If the class is 'broken' in one of these ways, then the bug lies there.

  12. #12
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Having an explicit copy constructor is not the same thing as making that copy constructor behave correctly for all usage patterns.
    I'm assuming that's what Mario meant.

  13. #13
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    The usage rules are provided by the class implementer and exposed through the interface. The user of the class has no other choice than to follow these rules, derive, or create his own implementation.

    Of course, bugs in the implementation of the class will render it... useless for the most part. And needless to say that an explicit and conscious negation of a suitable copy constructor and assignment operator will not allow the example the OP provided. But that type of implementation, again, is exposed through the interface. The user must know how to interpret the class usage.

    But all things equal, and that is what I believe the point of the OP was, there is nothing wrong or "bugable" in returning an object by value.

    We could probably waste a few good forum pages discussing situations where this would not be possible. None of them though would negate the previous paragraph.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  14. #14
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by swoopy
    I'm assuming that's what Mario meant.
    Absolutely.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  15. #15
    Registered User
    Join Date
    Nov 2005
    Posts
    4
    Quote Originally Posted by Mario F.
    But all things equal, and that is what I believe the point of the OP was, there is nothing wrong or "bugable" in returning an object by value.
    Quite.. I realized there inumerable ways for you to break code that returns in this way (e.g. if testA was storing a reference to another temporary object on the stack). But that wasn't point of OP, I was asking that if you don't do any craziness with pointers or references inside of getA() or in the class itself, is that still a potentially unsafe operation.

    I think the consensus is no... Thanks for all the replies

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. is it ok like that?
    By ExDHaos in forum C++ Programming
    Replies: 8
    Last Post: 05-23-2009, 09:02 AM
  2. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  3. can some one please tell me the cause of the error ?
    By broli86 in forum C Programming
    Replies: 8
    Last Post: 06-26-2008, 08:36 PM
  4. Alegro closes out on me
    By campsoup1988 in forum C++ Programming
    Replies: 8
    Last Post: 04-03-2006, 10:40 AM
  5. C++ FTP class won't work
    By lord mazdak in forum C++ Programming
    Replies: 8
    Last Post: 12-18-2005, 07:57 AM