Reputation: 561
I'm looking into C++11 move constructors but something doesn't work. In fact the issue is even before I started writing such a constructor. Here's a code snipped:
#include <iostream>
#include <string>
#include <sstream>
class Object {
static std::ostream& log(Object &obj) {
std::cout << "Object::id = " << obj.mId << "::";
return std::cout;
}
unsigned mId = 0;
std::string *mText = nullptr;
unsigned nextUniqueId() const {
static unsigned id = 0;
return ++id;
}
const std::string textInfo() const {
std::ostringstream oss;
oss << "mText @ " << &mText;
if (mText) oss << " = " << *mText;
return oss.str();
}
public:
Object() = delete;
Object& operator= (const Object&) = delete;
explicit Object(const std::string& str) : mId(this->nextUniqueId()), mText(new std::string(str)) {
Object::log(*this) << "constructor::one-argument\n";
}
Object(const Object& obj) : mId(this->nextUniqueId()), mText(new std::string(*obj.mText)) {
Object::log(*this) << "constructor::copy\n";
}
virtual ~Object() {
Object::log(*this) << "destructor::" << this->textInfo() << "\n";
if (mText) {
delete mText;
mText = nullptr;
}
}
};
static Object get_object() {
return Object("random text");
}
int main(int argc, char **argv) {
Object a("first object"); // OK
/*
* Expected behaviour: inside get_object() function new Object is created which is then copied into
* variable b. So that new ID should be given.
*/
Object b = get_object(); // What the hell?! Not what expected! Why?
std::cout << std::endl;
return 0;
}
The expected output is similiar to this:
Object::id = 1::constructor::one-argument
Object::id = 2::constructor::one-argument
Object::id = 2::destructor::mText @ 0x7fff32c25f70 = random text
Object::id = 3::constructor::copy
Object::id = 3::destructor::mText @ <DIFFERENT THAN IN ID=2> = random text
Object::id = 1::destructor::mText @ 0x7fff32c25f90 = first object
I get this instead:
Object::id = 1::constructor::one-argument
Object::id = 2::constructor::one-argument
Object::id = 2::destructor::mText @ 0x7fff32c25f70 = random text
Object::id = 1::destructor::mText @ 0x7fff32c25f90 = first object
which looks like variable b
is created on spot (something like inline
maybe?). Frankly speaking I don't know what's going on, can anyone explain?
Upvotes: 1
Views: 109
Reputation: 208323
That is called return value optimization or RVO. The compiler opted to create the temporary returned by get_object()
directly in the memory location of b
in main
. It is sanctioned by the standard and a very common optimization.
Upvotes: 3
Reputation: 4411
The compiler is allowed to apply "return value optimization" RVO and that's why the copy is optimized out. Note that the standard allows this despite the side effects related to the output message
Upvotes: 1