tags:

views:

402

answers:

7

HI,

I have this query about smart pointers.

I heard from one of my friends that smart pointers can almost always replace raw pointers. but when i asked him what are the other cases where smart pointers cannot replace the raw pointers,i did not get the answer from him.

could anybody please tell me when and where they cannot replace raw pointers?

+10  A: 
  1. Passing pointers to legacy APIs.
  2. Back-references in a reference-counted tree structure (or any cyclic situation, for that matter). This one is debatable, since you could use weak-refs.
  3. Iterating over an array.

There are also many cases where you could use smart pointers but may not want to, e.g.:

  1. Some small programs are designed to leak everything, because it just isn't worth the added complexity of figuring out how to clean up after yourself.
  2. Fine-grained batch algorithms such as parsers might allocate from a pre-allocated memory pool, and then just blow away the whole pool on completion. Having smart pointers into such a pool is usually pointless.
Marcelo Cantos
well 2. needs a weak pointer, not necessarily a raw pointer
jk
Why can't you iterate over an array with a smart pointer?
David Thornley
@David, because there's no point, since you know you don't own the elements of the array (you're just traversing it) and coordinating with whoever owns the array would be very complicated. Besides, it might be a stack-allocated array requiring no memory management at all.
Marcelo Cantos
@jk, good point.
Marcelo Cantos
I believe that smart_ptr allows you to overload the function which cleans up the memory. Hence, it's quite concievable that a memory pool would work just fine with a smart_ptr as long as your clean-up function was properly coordinated with your creation function.
wheaties
I find 1 and 3 straw men. On 1, most smart pointers have some sort of `get`, so you can still pass the contained pointer. And 3 isn't even a situation that matters. That's like saying "4. An integer. 5. A float." etc for each type. It just doesn't apply. And 2 is solved with a weak pointer.
GMan
@Marcelo: The question was things you can't do with smart pointers, not situations where smart pointers aren't useful.
David Thornley
@David, @GMan: in which case saying "there is nothing you can do with a raw pointer that you can't do with a smart pointer, because a smart pointer can return a raw pointer, and you can use that" rather misses the point IMO. Surely this is a question about what raw pointers are needed for, not a question about whether you can shove a smart pointer into some context where it doesn't help. I'm sure you can, but why would you?
Steve Jessop
@David, the question was about where you cannot replace raw pointers with smart pointers. Do you disagree with my statement to the effect that you cannot replace raw pointers with smart pointers in legacy APIs?
Marcelo Cantos
@GMan: On 1, the fact that you can fetch a raw pointer from a smart pointer is not only missing the point, but it's also wrong. A legacy API might feed you a raw pointer in the middle of some struct that you have to then use to access some data. You simply can't avoid working with raw pointers entirely. On 3, I'm talking about looping thus: `for (char* c = buf; *c; ++c) ...`; this is a very common idiom and it is difficult to imagine how you would even introduce a smart-pointer here, let alone why.
Marcelo Cantos
@Steve @Marcelo: I've missed the point of the question, then. If you're getting a pointer somehow and don't own it, obviously a smart pointer, which encapsulates ownership, doesn't apply.
GMan
+3  A: 

An API that is going to be called from C, would be an obvious example.

anon
+2  A: 

interaction with legacy code. if the api needs a raw pointer you need to provide a raw pointer even if once its in your code you wrap it in a smart pointer.

jk
+1  A: 

If you have a situation where a raw pointer is cast to an intptr_t and back for some reason, it cannot be replaced by a smart pointer because the casting operation would lose any reference counting information contained in the smart pointer.

Ferruccio
+3  A: 

Depends on the smart pointer you use. std::auto_ptr is not compatible with STL containers.

stonemetal
+3  A: 

It's a matter of semantics:

  • smart pointer: you own (at least partly) the memory being pointed to, and as such are responsible for releasing it
  • regular pointer: you are being given a handle to an object... or not (NULL)

For example:

class FooContainer
{
public:
  typedef std::vector<Foo> foos_t;

  foos_t::const_iterator fooById(int id) const; // natural right ?
};

But you expose some implementation detail here, you could perfectly create your own iterator class... but iterator usually means incrementable etc... or use a pointer

class FooContainer
{
public:
  const Foo* fooById(int id) const;
};

Possibly it will return NULL, which indicates a failure, or it will return a pointer to an object, for which you don't have to handle the memory.

Of course, you could also use a weak_ptr here (you get the expired method), however that would require using shared_ptr in the first place and you might not use them in your implementation.

Matthieu M.
+1  A: 

It would be quite hard to implement smart pointers if at some point you don't use plain pointers.

I suppose it would also be harder to implement certain data structures with smart pointers. E.g freeing the memory of a regular linked list is quite trivial, but it would take some thought to figure out the combination of owning and non-owning smart pointers to get the same result.

UncleBens