0

I'm trying to understand the principles of C++11 rvalue references. Here's the example where rvalue reference to object still works, whereas object itself is already destroyed (according to output). Is this an underfined behaviour or something that has a logical explanation? Thanks

#include <iostream>
class MyClass
{
public:
    static int cnt;
    MyClass(const int& par) :
        m_par(par)
    {
        cnt++;
        std::cout<<"ctor called (par="<<m_par<<", cnt = "<<cnt<<std::endl;
    }
    MyClass(const MyClass& other)
    {
        cnt++;
        this->m_par = other.m_par;
        std::cout<<"Copy constructor (par="<<m_par<<", cnt = "<<cnt<<std::endl;
    }
    void PrintParamTimesTwo() const
    {
        std::cout<<"Param * 2 = "<<2*m_par<<", cnt = "<<cnt<<std::endl;
    }
    ~MyClass()
    {
        cnt--;
        std::cout<<"destr-r called (par = "<<m_par<<", cnt = " <<cnt<<std::endl;
    }
private:
    int m_par;
};
int MyClass::cnt {0};
MyClass&& GetInstance()
{
    MyClass inst1(10);
    MyClass inst2(20);
    bool condition {false}; // any value
    return condition ? std::move(inst1) : std::move(inst2);
}
void outer_foo()
{
    const MyClass&& objRef = GetInstance();
    objRef.PrintParamTimesTwo();
}
int main()
{
    outer_foo();
    std::cin.get();
}

The output is:

ctor called (par=10, cnt = 1
ctor called (par=20, cnt = 2
destr-r called (par = 20, cnt = 1
destr-r called (par = 10, cnt = 0
Param * 2 = 40, cnt = 0 
  • 1
    You should print the adress of this or at least identify the object. What you are seeing is simply the counter being in/decremented – NoDataFound Feb 23 '20 at 12:22
  • @NoDataFound, have printed the addresses, didn't get any easier: the object, whose PrintParamTimesTwo() method was called, is the same object "inst2" in method "GetInstance()" – Ivan Sazhin Feb 23 '20 at 12:33
  • @L. F., i'm not sure it does... I've seen that topic, yes, but rvalues might be somewhat different – Ivan Sazhin Feb 23 '20 at 12:49
  • 1
    Don't overthink it; there is no fundamental difference between `T a; T& r = a;` and `T b; T&& r = std::move(b);` except for value categories. – L. F. Feb 23 '20 at 12:49
  • @L. F., doesn't std::move() move contents of "inst1" outside of function GetInstance() ? – Ivan Sazhin Feb 23 '20 at 13:47
  • No. std::move doesn’t move at all. unless you pass the rvalue to a move constructor or move assignment operator, it is a no-op. – L. F. Feb 23 '20 at 14:21

0 Answers0