Search code examples
c++c++11referencemoveobject-lifetime

How to extend lifetime of the local variable or what is right way to use references


I was developing some class and bumped for this question. Consider I have following class:

struct A
{
    int *p;
    A() 
    {
        p = new int(1); 
        cout << "ctor A" << endl; 
    }
    A(const A& o) 
    { 
        cout << "copy A" << endl;
        p = new int(*(o.p));
    }
    A(A&& o) 
    {
        cout << "move A" << endl;
        p = std::move(o.p);
        o.p = NULL;
    }
    A& operator=(const A& other)
    {       
        if (p != NULL)
        {
            delete p;
        }
        p = new int(*other.p);
        cout << "copy= A" << endl;
        return *this;
    }
    A& operator=(A&& other)
    {       
        p = std::move(other.p);
        other.p = NULL;
        cout << "move= A" << endl;
        return *this;
    }
    ~A()
    {
        if(p!=NULL)
            delete p;
        p = NULL;
        cout << "dtor A" << endl;
    }
};

And following class which has A as a property:

class B {
public:
  B(){}
  A myList;
  const A& getList() { return myList; };
};

And this function which checks for some variable value and returns different objects in different cases:

B temp;
A foo(bool f)
{
    A a;
    *a.p = 125; 
    if (f)
        return a;
    else
    {
        return temp.getList();
    }
}

Now, I am want to use this function like this:

A list1 = foo(true);
if(list1.p != NULL)
    cout << (*list1.p) << endl;

cout << "------"<<endl;
A list2 = foo(false);
if (list2.p != NULL)
    cout << (*list2.p) << endl;

The purpose of this situation is:

Function foo should return (or move) without copying some local object with changes in p if argument is true, or should return property of global variable temp without calling copy constructors of A (i.e. return reference of myList) and also it should not grab myList from B (it should not destroy myList from B, so std::move can not be used) if argument is false.

My question is:

How should i change function foo to follow upper conditions? Current implementation of foo works right in true case and moving that local variable, but in case false it calls copy constructor for list2. Other idea was to somehow extend lifetime of local variable, but adding const reference did not work for me. Current output is:

ctor A
ctor A
move A
dtor A
125
------
ctor A
copy A
dtor A
1
dtor A
dtor A
dtor A

Solution

  • If you can change B to

    class B {
    public:
      B(){}
      std::shared_ptr<A> myList = std::make_shared<A>();
      const std::shared_ptr<A>& getList() const { return myList; };
    };
    

    then foo can be:

    B b;
    std::shared_ptr<A> foo(bool cond)
    {
        if (cond) {
            auto a = std::make_shared<A>();
            *a->p = 125; 
    
            return a;
        } else {
            return b.getList();
        }
    }
    

    Demo

    Output is

    ctor A
    ctor A
    125
    ------
    1
    dtor A
    dtor A