5

I am not experienced in handling of the memory in a C++ program, so I would like a piece of advice in that case:

I want to create a new Object in a function in a class which is essential till the end of the program. As far as I am concerned, if I use the operator new, I should sometimes delete it. Taking into account that it must be initialized inside a class, when and how must I finally delete it?

Unihedron
  • 10,902
  • 13
  • 62
  • 72
arjacsoh
  • 8,932
  • 28
  • 106
  • 166

4 Answers4

5

I suggest the smart pointer idiom

#include <memory>

struct X 
{
     void foo() { }
};

std::share_ptr<X> makeX() // could also be a class member of course
{
    return std::make_shared<X>();
}

int main()
{
     std::share_ptr<X> stayaround = makeX();

     // can just be used like an ordinary pointer:

     stayaround->foo();

     // auto-deletes <sup>1</sup>
}

If the pointer is truly a static variable, you can substitute a unique_ptr (which works similarly, but passes ownership on assignment; this means that the pointer doesn't have to keep a reference count)

Note To learn more about C++ smart pointers in general, see   smart pointers (boost) explained  

Note If you don't have the TR1/C++0x support for this, you can just use Boost Smartpointer


1 unless you are leaking copies of the shared_ptr itself; that would be some strange use of smart pointers previously unseen :)

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    Why are you using `std::shared_ptr` by default? Why not `std::unique_ptr`? – Nawaz Nov 29 '11 at 12:49
  • @Nawaz: because it applies more generally. For one thing, I _assume_ that the code consists of more than a single function body and the pointer _will_ get passed around. Unique pointer semantics might apply, but not in general. – sehe Nov 29 '11 at 12:50
  • @sehe: If it applies more generally, then why does `std::unique_ptr` exist? – Nawaz Nov 29 '11 at 12:55
  • @Nawaz: are you trolling me :) See my answer... ([I _think_ you know the answer these questions yourself](http://stackoverflow.com/users/415784/nawaz?tab=badges) in a jiffy - did I say something wrong?) – sehe Nov 29 '11 at 12:55
  • @sehe: Actually, I've seen many people using `std::shared_ptr` by default, and rarely see `std::unique_ptr`, when I think `std::unique_ptr` should be used more generally than `std::shared_ptr`. – Nawaz Nov 29 '11 at 13:03
  • @Nawaz: well that's just wrong. Perhaps you mean _more often_ or _more widely_. But in most cases where a `unique_ptr` is used you _can_ substitute a `shared_ptr` (forgetting about cycles for now), whereas vice-versa that is not the case. So, `shared_ptr` applies _more generally_. – sehe Nov 29 '11 at 13:05
  • Updated answer with a link to a general explanation of [smart pointers in C++](http://stackoverflow.com/questions/569775/smart-pointers-boost-explained) – sehe Nov 29 '11 at 13:09
  • @sehe: Yeah, *more often* or *more widely* are better wordings, which I should have used. – Nawaz Nov 29 '11 at 13:12
  • The problem here is a simple one of semantics. In colloquial english, /generally/ means kind of works and implies /more often/ or /more widely/. In mathematics english, /general/ means works on more cases than the thing to which you are comparing. Stupid opposite meanings :) – McBeth Nov 29 '11 at 13:12
  • @McBeth: The issue was one of a (harmless) misunderstanding, indeed. Getting OT, I don't see the _opposite meanings_: I think in _both_ contexts _`more generally`_ does imply _`more widely`_ or _`more often`_; The problem was recognizing when _`more generally`_ was being used in the _stricter_ sense of the word. Now to make the paradox explicit, I **do agree** that the _`less general`_ smart pointer should be used _`more widely`_ in this case! Note that `less general` applies to the pointer flavour, and `more widely` applies the application contexts - no contradiction – sehe Nov 29 '11 at 13:26
  • @sehe: Haha. Nice explanation in the comment. And +1 for the answer, and the link to other topic. – Nawaz Nov 29 '11 at 13:29
  • @sehe When I talk to non-math people, something working "in general" carries the implication that it doesn't work in the specific. When I talk to math people, something working "in general" works always. – McBeth Nov 29 '11 at 13:38
2

You can use the smart pointer as suggested by Sehe or you can create a static object in the function and return a reference to it. You need not explictly delete the object, when the process terminates the object will be deleted. Like:

struct X {};

X& makeX() // could also be a class member of course
{
    static X x;
    return x;
}

int main()
{
     X& stayaround = makeX();
}
Asha
  • 11,002
  • 6
  • 44
  • 66
2

Edit: Using some sort of smart pointer is often a good idea, but I believe it is still essential to have a solid understanding of manual memory management in C++.

If you want an object in a class to persist until the end of the program, you can simply make it a member variable. From what you've said, there's nothing to suggest you need to use new or delete here, just make it an automatic variable. If you did want to use new and delete for practice, you should read up on constructors and destructors for a class (you can and will use new and delete outside of classes, but I'm trying to keep this relevant to your question). Here's one I prepared earlier:

class Foo
{
    public:
        Foo();  // Default constructor.
        ~Foo(); // Destructor.

    private:
        int *member;
}

Foo::Foo() // Default constructor definition.
{
    member = new int; // Creating a new int on the heap.
}

Foo::~Foo() // Destructor.
{
    delete member; // Free up the memory that was allocated in the constructor.
}

This is a simple example, but it will hopefully help you out. Note that the variable will only persist as long as the object is alive. If the object is destroyed or goes out of scope, the destructor will be called and the memory will be freed.

Chris Parton
  • 1,052
  • 9
  • 16
  • That is almost what I intended to do. What though concerns me is when I should invoke the destructor, if the Object is not "visible" in main. Should I make a function to pass it in main and then delete? – arjacsoh Nov 29 '11 at 12:56
  • 2
    The beauty of the destructor is that you don't need to invoke it. Not only that, you *cannot* invoke it. When your object instance goes out of scope (e.g. the program ends), the object's destructor is called which deletes the memory allocated by `new`. If you were to create an instance of `Foo` on the heap, e.g. `Foo f = new Foo;`, then you would have to call `delete f;` when you were done with it. Calling `delete f;` deletes the instance off the heap, but not before calling `f`'s destructor, which will delete the memory used by the `member` integer. – Chris Parton Nov 29 '11 at 12:59
  • Does anything change if the initialization of the member occurs in another from the constructor method? Should I then check in the destructor if the pointer is not NULL and aftewards delete it? – arjacsoh Nov 29 '11 at 13:27
  • At the end of the day, your member needs to be initialised and then later deleted (if you want to use it :P). It doesn't matter if it's initialised in the constructor or later on (e.g. setter method), as long as you do it. Yes, you should check that the pointer != 0 before deleting it in any nontrivial application. Also, whenever you `delete` a pointer, you should set it to 0 afterwards so that you can't accidentally reference the deleted memory. You don't have to worry about setting pointers to 0 in the destructor as much, as the containing object is being destroyed. – Chris Parton Nov 29 '11 at 13:30
0

On most operating systems (in particular Linux), if you allocate an object pointer with new Object, and don't bother delete-ing because you'll need it till the program ends, no harm is really done. There is some memory leak inside your program (you can use valgrind to hunt such leaks) but the kernel will release all the memory used by a process when it has ended.

A better alternative is to have a singleton class for the application data, like e.g. QApplication in Qt, ahd construct a single instance in that class early in your main, and have that class contain a smart or dumb pointer to your Object. The destructor should delete that object.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547