1

From c++ 11 i can write code without create and deleting raw pointers. But is it the right way to go- Should i always use smart pointers (either shared, unique or weak) or are there situations in which i should delete objects by myself?

Erik Sapir
  • 23,209
  • 28
  • 81
  • 141

2 Answers2

23

It is hard to imagine situations where you would want to manually delete an object, so in that sense, the answer to your question is "yes, always use smart pointers".

However, raw pointers do have another use case. Smart pointers are all about conferring ownership semantics. A unique_ptr has exclusive ownership of the object it points to, and will destroy the object when the pointer goes out of scope. A shared_ptr implements shared ownership, and the object will be destroyed when the last shared pointer goes out of scope.

Raw pointers are still useful for cases where you want to point to an object without indicating any kind of ownership. You're just pointing to an object you know exists, and that someone else (who owns it) will delete it when the time comes.

Raw pointers are for pointing to objects. Smart pointers are for owning objects.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • 1
    Most deletes in well written code are `delete this`. Does this count as "manually deleting" an object. If you don't want explicit control of the lifetime of an object, the first question to ask is: why am I dynamically allocating it? – James Kanze Feb 12 '14 at 18:06
  • 2
    @JamesKanze: I have not seen a lot of "well written" code containing `delete this`. And I am pretty sure we disagree on what well written C++ code is. Apart from that, I'm not really sure how to answer you. I'm not sure what you mean by "explicit control" over an object's lifetime. Do I have explicit control if I use a `unique_ptr` or a `shared_ptr`? I control exactly when it should be deleted, but I don't explicitly put code at the site where I want it deleted. I typically *do* want to control the lifetime of an object. That is why I use smart pointers. – jalf Feb 12 '14 at 18:39
  • I'm also not sure what exactly you consider to be "dynamically allocated". A `std::vector` internally uses dynamic allocation, but it's not directly visible to the user. Are you suggesting we shouldn't even do that, and let the application rely exclusively on the stack regardless of the amount of memory you want to allocate? – jalf Feb 12 '14 at 18:41
  • 1
    The easiest way is to give an example. If you have a class like `BankAccount`, it's an entity object, which supports different operations, like `deposit`, `withdraw`, `close`, etc. The operation `close`, in particular, will make a certain number of verifications, and then, if everything is OK, close the account by doing `delete this;`. The object lifetime is determined by the program specifications, in reaction to external events or requests. It's the logical way of handling entity objects, and very few other objects should be dynamically allocated (at the application level, at least). – James Kanze Feb 12 '14 at 18:54
  • 1
    With regards to `std::vector`: objects with indeterminate size, like vectors, strings and graphs _will_ use dynamic memory in their implementation. Their clients shouldn't see it, and of course, they will manage the memory and delete it as appropriate (and at the latest, in their destructor). But surely you wouldn't recommend using a smart pointer for the memory in `std::vector`. (Of course, `std::vector` is a special case, since it separates allocation and initialization, and the implementation code probably never uses the `delete` operator.) – James Kanze Feb 12 '14 at 18:58
1

There are really very few cases where you'd want to use a smart pointer. In most applications, either most deletes will be delete this, or if the application is transactional, the transaction manager will take care of the delete. In cases where this doesn't apply, you generally don't want to use dynamic allocation to begin with. About the only times you'll use smart pointers:

  • For some reason or another, you cannot make the object fully operational in the constructor, but have to follow up with additional actions before it is active. In this case, it makes sense to keep it in an std::unique_ptr until the object is fully active, then call release.

  • You really want value semantics, but you also need polymorphism. In this case, use some sort of shared pointer. (But beware of cycles.) If the object is mutable, beware too, since you'll end up with reference semantics.

  • You really want value semantics (with deep copy), but the profiler shows that the cost of copying is too high, you might also consider some sort of shared pointer. This has its dangers, but for large blocks of immutable data, can be a good solution.

But for starters, you should always ask yourself: why am I allocating this object dynamically. The most frequent valid reason is that it is an entity object, with a lifetime defined by program logic (i.e. its lifetime ends as a result of some external event). In such cases, smart pointers will cause more problems than they solve.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • no dynamic allocation? how would you load a bunch of assets for a video game? And your first point is wrong if you apply RAII. – Syl Feb 12 '14 at 20:56
  • @Syl I didn't say no dynamic allocation. I said that you use dynamical allocation only when appropriate. In a video game, there will be a lot of dynamically allocated objects: those representing the player, and the various objects. But they're all entity objects; you wouldn't manage them with a smart pointer (or at least, not any smart pointer I've seen). If a monster zaps you with something which destroys your armor, your armor should be destroyed, regardless; you don't want it hanging around because there's still a shared pointer pointing to it. – James Kanze Feb 13 '14 at 09:05
  • 1
    @Syl And my first point is precisely RAII. As long as the "resource" (the newly created object) is ephemeral, and should be destructed if it goes out of scope, you keep it in a smart pointer. Of course, once it ceases to be ephemeral, and must live beyond the scope, you have to take it out of the smart pointer, because RAII (which despite its name, is more concerned with automatic destruction) no longer applies. – James Kanze Feb 13 '14 at 09:07