Thread: Passing temporary variable by value

  1. #1
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99

    Passing temporary variable by value

    Code:
    #include <iostream>
    using namespace std;
    
    struct X
    {
        int i;
        X(int j = 0): i(j){cout << "constructor\n";}
        X(const X& x): i(x.i){cout << "copy constructor\n";}
        ~X(){cout << "destructor\n";}
        X& operator=(const X& x);
    };
    
    X& X::operator=(const X& x)
    {
        cout << "assignment operator\n";
        if (this != &x) i = x.i;
        return *this;
    }
    
    X y(int i)
    {
        cout << "in y()\n";
        return X(i);//<-----------------This
    }
    
    //const X& func(const X& x)
    const X& func(X x)//<------------ends up here
    {
        cout << "in func()\n";
        return x;
    }
    
    int main()
    {
        func(y(99));
        return 0;
    }
    When I run the above program, the copy constructor is not called when the temporary variable from y() is passed by value to func(). I thought the whole point of passing by value is that a new object is made that is initialised with the value being passed. Does that only apply when the function argument is a global or static object?

    Can anyone enlighten me as to why that should be the case?

    Thanks.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The compiler can sometimes optimize away the constructor calls, that's the only thing I can think of.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    The compiler is allowed to optimize out that temporary copy.

    Also keep in mind that func() is returning a reference to a local variable which is bad news. Note that the compiler would not be able to perform this optimization if you changed your code to:

    Code:
    int main()
    {
        X x(99);
        func(x);
        return 0;
    }

  4. #4
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Thanks.

    Would the
    Code:
    const X& func(const X& x
    ) version be safe?

  5. #5
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    It depends on how the function is called.

    Code:
    X& x = func(X());
    would not be safe.
    Code:
    X& x = funct(existingX);
    would be safe as long as existingX stayed in scope.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by bithub
    It depends on how the function is called.

    Code:
    X& x = func(X());
    would not be safe.
    The X& should be changed to const X&. Once that is done, are you sure that that would not be safe? Copy constructor elision aside, I thought that that would result in the reference parameter for func() being bound to a copy of the temporary returned from the constructor invocation. The temporary to which reference returned from func() is bound would then be copied to another temporary to which x would then be bound. The lifetime of this temporary persists for the lifetime of the reference x.

    Quote Originally Posted by bithub
    X& x = funct(existingX);[/code]
    would be safe as long as existingX stayed in scope.
    I think that existingX must remain in scope, since there is no way for the reference x to go out of scope after existingX goes out of scope.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    The X& should be changed to const X&. Once that is done, are you sure that that would not be safe?
    You're right, I completely missed the const in his prototype.

    I think that existingX must remain in scope, since there is no way for the reference x to go out of scope after existingX goes out of scope.
    I used the term scope to mean the lifetime of the passed object. What i meant was for him to watch out for situations similar to:
    Code:
    existingX = new X();
    X& x = funct(*existingX);
    delete existingX;
    // use x here...
    which would obviously cause problems.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 01-29-2006, 06:57 PM
  2. Make a variable available everywhere without passing?
    By Austin in forum C++ Programming
    Replies: 9
    Last Post: 03-03-2005, 11:38 AM
  3. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  4. About classes and HINSTANCE variable to Main
    By conright in forum Windows Programming
    Replies: 2
    Last Post: 01-01-2003, 08:00 PM
  5. creating class, and linking files
    By JCK in forum C++ Programming
    Replies: 12
    Last Post: 12-08-2002, 02:45 PM