Search code examples
c++visual-c++c++11

Can't pass temporary object as reference


This is a very minimal example:

class Foo
{
public:
    Foo(int x) {};
};

void ProcessFoo(Foo& foo)
{
}

int main()
{
    ProcessFoo(Foo(42));
    return 0;
}

The above compiles fine on Visual Studio, but generates an error on Linux and Mac.

Compiling the above generates this:

$ g++ -std=c++11 -c newfile.cpp

newfile.cpp: In function ‘int main()’:
newfile.cpp:23:23: error: invalid initialization of non-const reference of type ‘Foo&’ from an rvalue of type ‘Foo’
     ProcessFoo(Foo(42));
                       ^
newfile.cpp:14:6: note: in passing argument 1 of ‘void ProcessFoo(Foo&)’
 void ProcessFoo(Foo& foo)

I've found three workarounds:

  1. Create a temp variable for the invocation of ProcessFoo.

Like this:

Foo foo42(42);
ProcessFoo(foo42);
  1. ProcessFoo takes a const reference: void ProcessFoo(const Foo& foo)

  2. ProcessFoo just lets Foo get passed by value. void ProcessFoo(Foo foo)

Why is the compiler forbidding my original code? (What is it guarding against)? What is it about each of the three workarounds above that satisfies the compiler? What would MSVC allow it, but not g++?


Solution

  • By design, C++ only allows a temporary to be passed to a const reference, value, or rvalue reference. The idea is that a function taking a non-const reference parameter is stating that it wants to modify the parameter and allowing it to go back to the caller. Doing so with a temporary is meaningless and most likely an error.

    And I don't know what version of g++ you're running. It doesn't work here: http://coliru.stacked-crooked.com/a/43096cb398cbc973