Catching return value in a const reference needed?

E

Eric Lilja

Hello, consider this complete program:
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class Hanna
{
public:
Hanna(const string& s)
:
s_(s)
{ cout << "normal ctor, name = " << s_ << endl; }

Hanna(const Hanna& inst)
:
s_(inst.s_)
{ cout << "copyctor, name = " << s_ << endl; }

~Hanna() { cout << "cleaning up " << s_ << endl; }

Hanna& operator=(const Hanna& rhs)
{
s_ = rhs.s_;

cout << "in operator=(), name = " << s_ << endl;

return *this;
}

private:
string s_;
};

static Hanna
func(const string& s)
{
Hanna anobj(s);

return anobj;
}

int
main()
{
cout << "Testing catching return value in normal object." << endl;

{
Hanna a = func("not catching const ref");

(void)a;
}

cout << "\nTesting catching return value in a const reference" <<
endl;

{
const Hanna& b = func("catching const ref");

(void)b;
}

return 0;
}


When run, the outut is:
$ ./runme
Testing catching return value in normal object.
normal ctor, name = not catching const ref
cleaning up not catching const ref

Testing catching return value in a const reference
normal ctor, name = catching const ref
cleaning up catching const ref

The program has been compiled with optimizations disabled (and
debugging turned on). I thought that I had to catch the return value in
a const reference (if possible), if I wanted to avoid ctor/dtor calls
but seems I dont have to...is this optimization part of the C++
specification?

/ E
 
T

Tomás

static Hanna
func(const string& s)
{
Hanna anobj(s);


Here you create a local object of the type "Hanna".

return anobj;


Here you return a local object (by value) of the type "Hanna".

}

int
main()
{
cout << "Testing catching return value in normal object." << endl;

{
Hanna a = func("not catching const ref");


For clarity, maybe change that to:

Hanna a = func("Initialising local object with return value");

(void)a;
}

cout << "\nTesting catching return value in a const reference" <<
endl;

{
const Hanna& b = func("catching const ref");


Hanna b = func("Binding return value to a local const reference");
(void)b;
}

return 0;
}


When run, the outut is:
$ ./runme
Testing catching return value in normal object.
normal ctor, name = not catching const ref
cleaning up not catching const ref

Testing catching return value in a const reference
normal ctor, name = catching const ref
cleaning up catching const ref

The program has been compiled with optimizations disabled (and
debugging turned on). I thought that I had to catch the return value in
a const reference (if possible), if I wanted to avoid ctor/dtor calls
but seems I dont have to...is this optimization part of the C++
specification?


Yes, it's called something like "Eliding constructors"; it's an
optimization. The compiler though doesn't have to perform this optimization.
Without it, I would expect there to be three objects created rather than
one:

1) The local object in "func".

2) The object returned from "func".

3) The local object in "main".


If you only need a const object, I would advocate going the const reference
route.

If you need a non-const object, you could do what you have done, or you
could go for more elaborate means.

-Tomás
 
V

Victor Bazarov

Eric said:
Hello, consider this complete program:
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class Hanna
{
public:
Hanna(const string& s)
:
s_(s)
{ cout << "normal ctor, name = " << s_ << endl; }

Hanna(const Hanna& inst)
:
s_(inst.s_)
{ cout << "copyctor, name = " << s_ << endl; }

~Hanna() { cout << "cleaning up " << s_ << endl; }

Hanna& operator=(const Hanna& rhs)
{
s_ = rhs.s_;

cout << "in operator=(), name = " << s_ << endl;

return *this;
}

private:
string s_;
};

static Hanna

Prefer placing functions like that in an unnamed namespace. Using
'static' with functions has been deprecated.
func(const string& s)
{
Hanna anobj(s);

return anobj;
}

int
main()
{
cout << "Testing catching return value in normal object." << endl;

{
Hanna a = func("not catching const ref");

(void)a;
}

cout << "\nTesting catching return value in a const reference" <<
endl;

{
const Hanna& b = func("catching const ref");

(void)b;
}

return 0;
}


When run, the outut is:
$ ./runme
Testing catching return value in normal object.
normal ctor, name = not catching const ref
cleaning up not catching const ref

Testing catching return value in a const reference
normal ctor, name = catching const ref
cleaning up catching const ref

The program has been compiled with optimizations disabled (and
debugging turned on). I thought that I had to catch the return value
in a const reference (if possible), if I wanted to avoid ctor/dtor
calls but seems I dont have to...is this optimization part of the C++
specification?

Yes. The compiler is allowed to optimise away creation of a temporary
when copy-constructing objects. The statement

Hanna a = func();

can end up optimised in such way that there is no temporary and the
function's return value is placed directly in the object being born.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,150
Latest member
MakersCBDReviews
Top