dev-null dev-null - 1 month ago 5x
C++ Question

Return by value does not create a new object

I wanted try out what I read about returning by value in C++ (that it's the same as with passing by value in that new object is create) I have code like this:

#include <iostream>

using namespace std;

class Kar{

int n;
static int no;

n = ++Kar::no;
cout << "Creating Kar " << n << endl;

Kar(Kar &k){
n = ++Kar::no;
cout << "Copying Kar " <<k.n<< " to new Kar " << n << endl;

cout << "Destroying Kar "<< n << endl;

Kar& operator= (const Kar &k);

Kar& Kar::operator= (const Kar &k){

cout << "Assigning Kar "<< k.n <<" to Kar "<< this->n << endl;
return *this;

int Kar::no;

Kar foo(){
cout << "Starting foo()" << endl;
Kar k;
cout << "Finishing foo()" << endl;
return k;

int main(int argc, char **argv) {
cout << "Starting!" << endl;

Kar k;
// Kar k2 = foo();

cout << "Finishing!" << endl;
return 0;

Terminal output is this:

Creating Kar 1
Starting foo()
Creating Kar 2
Finishing foo()
Assigning Kar 2 to Kar 1
Destroying Kar 2
Destroying Kar 1

  1. I would expect the behavior in
    to be: a. create Kar 2 b. copy it to Kar 3 and return it (subsequently assigning Kar 3 to Kar 1). Why not?

  2. If I uncomment
    Kar k2 = foo();
    I get compiler message:

    error: no matching function for call to Kar::Kar(Kar)

End of course I cannot add constructor
Kar(Kar k){ }
because that's invalid. What does this mean? Why is not constructor
Kar(Kar &k)
used for this case?


The behavior you are seeing is called the return value optimization. So instead of the compiler creating a temp object for the return value, it will eliminate that, and use the object already created after the return statement.

Regarding your second question, you are getting a compiler error because you can't bind non const temporaries (r-values) to l-value references (BTW MSVC accepts this but it's a non standard behavior). Try changing your copy constructor to this:

Kar(const Kar& kar);