Question

I'm an Objective-C programmer, and am recently starting C++, and I've stumbled into this question on my code's organization:

std::list<char *> stuff = std::list<char *>();
thing *object = new thing(stuff);

Where stuff would be an object that I'd need for the lifetime of my class (that is, until it gets destructed), how to avoid losing it?

On Objective-C, I could simply call -retain on the constructor. On C++?

Was it helpful?

Solution

Do not use pointers when you don't need them, and don't use owning raw pointers (unless you have a very good reason for them).

Use automatic storage duration:

std::list<char> stuff;
thing object{stuff};

The constructor of thing would take std::list<char> as its argument:

#include <utility> // for std::move

class thing {
public:
    explicit thing(std::list<char> stuff_) : stuff(std::move(stuff_)) {}

private:
    std::list<char> stuff;
};

If you do it this way, the destructor of thing will be called when thing goes out of scope, implicitly calling the destructor of stuff. Many good C++ books explain this in great detail.

Unlike Objective-C, and C++ uses RAII rather than reference counting. The basic rule is: use automatic storage duration when possible, avoid raw owning pointers, and don't use new unless you have a good reason for it.

OTHER TIPS

The usual way would be to copy or move stuff into thing in the constructor of thing:

class thing {
public:
    thing(std::list<char*> stuff) : stuff(std::move(stuff)) {}
private:
    std::list<char *> stuff;
};

It's not clear how you are going to use stuff in your example, so I'm going to give you a few different options.

  1. thing stores its own copy of stuff.
    In this case your class stores an object of type std::list<char*>.

    class thing
    {
    public:
      thing(std::list<char*>& aList):m_list(alist){}
      std::list<char*> m_list;
    };
    

    When you construct thing copy of stuff is made and stored in the class. When the object is destructed it will automatically deallocate m_list.

  2. thing stores a weak reference to stuff.
    Your class will store a pointer (std::list<char*>* m_list) or reference (std::list<char*>& m_list). thing will be able to use your list in any way, but it shouldn't be in charge of resource management. If the list is in a smaller scope than thing then you'll be left with a hanging reference.

    thing getThing()
    {
    std::list<char*> list1;
    thing object1(list1);
    return object1; //bad - list will be deallocated, object1 will have a hanging reference
    }
    
  3. thing stores a shared pointer to stuff. This is the method that is most like retain in Objective C. C++ doesn't have automatic reference counting. If you want to store an object reference with shared ownership you can use an std::shared_ptr. thing stores std::shared_ptr<std::list<char*>> m_list.

    std::shared_ptr<std::list<char*>> stuff = std::make_shared<std::list<char*>>();
    thing object(stuff); //reference count incremented, even if stuff is destroyed object will still hold a valid reference
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top