Can I make a smart pointer to a smart pointer? - c++

I am brand new to C++ (and Stack Overflow!) so I apologize if this question has already been answered in some capacity, I just wasn't able to find exactly what I was looking for.
In a recent project, I created pointers to pointers (example: Tiger **tigerArray;) and wound up having memory leaks in my program, but I was never able to figure out why. I had a thought that maybe if I had done smart pointers instead of just pointers, that may have solved the problem?
So I'm curious, if I can create a pointer to a pointer, can I create a smart pointer to a smart pointer?
**Sorry I should update, I wasn't allowed to use vectors for this assignment, we had to use arrays

Smart points are generic; you can stick basically anything you want inside one. But you should decide the right tool for the job based on what it is you're trying to achieve. Smart pointers have fairly specific use cases. Pointers to pointers, on the other hand, have a couple different use cases:
pointer arrays of pointer arrays, for implementing 2D arrays. If this is what you're trying to achieve, consider using std::vector<std::vector<T>> or std::array<std::array<T, N>, M> if you know your array will always have size MxN.
pointer to a pointer, as used for modifying another pointer from a function. In this case, you should consider passing by reference. If you really need pointers in your code, you could modify one by passing as T*&, a reference to a pointer to T. But depending on what you're representing, you could just as well pass your data as std::vector<T>&, for example.
Smart pointers exist to automatically manage the lifetime of objects depending on how you want those objects to be used. They don't exist purely as a means of indirection that is open to many different usages, like raw pointers. My advice on which tool to use would be as follows:
If you need a simple resizable array of T, use std::vector<T>.
If you need a 2D resizable array of T, use std::vector<std::vector<T>>.
If you know you will always have N elements in your array, consider using std::array<T, N>.
If you need more structure, such as strict ordering or relationships, consider using std::set, std::map, std::multimap, std::queue, std::stack, etc
About smart pointers:
If you need an object that is light-weight to pass around but only ever has a single owner, or if you need to encapsulate a polymorphic object that is used in a single place, consider std::unique_ptr<T>
If you need an object to be used by multiple places in code which does not have a single sensible place of ownership and instead needs to have distributed ownership, use std::shared_ptr<T>
If you want to modify an object from inside a function such that the object will live for the duration of the function's needs, just pass by reference: T&
If you want to read from but not modify an object in a function where that object will be alive for the duration of the function's needs, pass by reference to const: const T&
EDIT:
After seeing that you are not allowed to use std::vector for your assignment, I realize I'm not really answering your updated question. But I still hope to give you (and future readers) some insight as to what smart pointers are for and what they're not for.
If your instructor is teaching C++ but not allowing you to use vectors, I would criticize them by saying that vector is an immensely important tool on the belt of the modern C++ developer, and its usage is far simpler and safer than the C-style alternatives that are still taught as being C++ in many outdated curriculums. The same goes other tools and techniques such as generally avoiding pointers, avoiding new and delete, and making good use of the containers and algorithms of the standard library, all of which helps you write cleaner, correcter, and efficient code.

Related

Raw pointer but modern way

I have to have a semantic stack in my project which is going to hold multiple types in it.
I aim to have my project to use modern C++.
What is the correct way to have a stack of any type ?
Equivalent version in java is Stack<Object>.
Which of these are correct?
Use void* and cast it to the type I want.
Something as 1 but using some smart pointers. (I don't know what)
std::any is for storing objects of any type (limitations may apply).
However, the entire design of storing any type is rarely ideal. Often, it's better to use variadic templates to keep polymorphism entirely compile time, or to have only a limited set of types (std::variant), or even to use an OOP hierarchy. Which is more appropriate depends on the use case.
void* pointers is a pure C stuff that is obsolete in C++.
You can use use smart pointers (such as unique_ptr or shared_ptr) when you dynamically allocate memory for your objects/variables/members. Do not wrap some API pointer objects that is not created by you in smart pointer objects. When you pass arguments into a function and you need to avoid copying of objects you better use references instead of pointers. However, you can use raw pointers in C++ but this is not recommended.

Writing more general pointer code

Assume that I want to write function that takes in a pointer. However I want to allow caller to use naked pointers or smart pointers - whatever they prefer. This should be good because my code should rely on pointer semantics, not how pointers are actually implemented. This is one way to do this:
template<typename MyPtr>
void doSomething(MyPtr p)
{
//store pointer for later use
this->var1 = p;
//do something here
}
Above will use duck typing and one can pass naked pointers or smart pointers. The problem occurs when passed value is base pointer and we need to see if we can cast to derived type.
template<typename BasePtr, typename DerivedPtr>
void doSomething(BasePtr b)
{
auto d = dynamic_cast<DerivedPtr>(b);
if (d) {
this->var1 = d;
//do some more things here
}
}
Above code will work for raw pointers but won't work for the smart pointers because I need to use dynamic_pointer_cast instead of dynamic_cast.
One solution to above problem is that I add new utility method, something like, universal_dynamic_cast that works both on raw pointers and smart pointers by selecting overloaded version using std::enable_if.
The questions I have are,
Is there a value in adding all these complexities so code supports raw as well as smart pointers? Or should we just use shared_ptr in our library public APIs? I know this depends on purpose of library, but what is the general feeling about using shared_ptr all over API signatures? Assume that we only have to support C++11.
Why doesn't STL has built-in pointer casts that are agnostic of whether you pass raw pointers or smart pointers? Is this intentional from STL designers or just oversight?
One other problem in above approach is loss of intellisense and bit of readability. This is the problem obviously in all duck typed code. In C++, however, we have a choice. I could have easily strongly typed my argument above like shared_ptr<MyBase> which would sacrifice flexibility for callers to pass whatever wrapped in whatever pointer but reader of my code would be more confident and can build better model on on what should be coming in. In C++ public library APIs, are there general preferences/advantages one way or another?
There is one more approach I have seen in other SO answer where the author proposed that you should just use template<typename T> and let caller decide if T is some pointer type or reference or class. This super generic approach obviously don't work if I have to call something in T because C++ requires dereferencing pointer types which means I have to probably create utility method like universal_deref using std::enable_if that applies * operator to pointer types but does nothing for plain objects. I wonder if there are any design patterns that allows this super generic approach more easily. Again, above all, is it worth going all these troubles or just keep thing simple and use shared_ptr everywhere?
To store a shared_ptr within a class has a semantic meaning. It means that the class is now claiming ownership of that object: the responsibility for its destruction. In the case of shared_ptr, you are potentially sharing that responsibility with other code.
To store a naked T*... well, that has no clear meaning. The Core C++ Guidelines tell us that naked pointers should not be used to represent object ownership, but other people do different things.
Under the core guidelines, what you are talking about is a function that may or may not claim ownership of an object, based on how the user calls it. I would say that you have a very confused interface. Ownership semantics are usually part of the fundamental structure of code. A function either takes ownership or it does not; it's not something that gets determined based on where it gets called.
However, there are times (typically for optimization reasons) where you might need this. Where you might have an object that in one instance is given ownership of memory and in another instance is not. This typically crops up with strings, where some users will allocate a string that you should clean up, and other users will get the string from static data (like a literal), so you don't clean it up.
In those cases, I would say that you should develop a smart pointer type which has this specific semantics. It can be constructed from a shared_ptr<T> or a T*. Internally, it would probably use a variant<shared_ptr<T>, T*> or a similar type if you don't have access to variant.
Then you could give it its own dynamic/static/reinterpret/const_pointer_cast functions, which would forward the operation as needed, based on the status of the internal variant.
Alternatively, shared_ptr instances can be given a deleter object that does nothing. So if your interface just uses shared_ptr, the user can choose to pass an object that it technically does not truly own.
The usual solution is
template<typename T>
void doSomething(T& p)
{
//store reference for later use
this->var1 = &p;
}
This decouples the type I use internally from the representation used by the caller. Yes, there's a lifetime issue, but that's unavoidable. I cannot enforce a lifetime policy on my caller and at the same time accept any pointer. If I want to ensure the object stays alive, I must change the interface to std::shared_ptr<T>.
I think the solution you want is to force callers of your function to pass a regular pointer rather than using a template function. Using shared_ptrs is a good practice, but provides no benefit in passing along the stack, since the object is already held in a shared pointer by the caller of your function, guaranteeing it does not get destroyed, and your function isn't really "holding on" to the object. Use shared_ptrs when storing as a member (or when instantiating the object that will become stored in a member), but not when passing as an argument. It should be a simple matter for the caller to get a raw pointer from the shared_ptr anyway.
The purpose of smart pointers
The purpose of smart pointers is to manage memory resources. When you have a smart pointer, then you usually claim unique or shared ownership. On the other hand, raw pointers just point to some memory that is managed by someone else. Having a raw pointer as a function parameter basically tells the caller of the function that the function is not caring about the memory management. It can be stack memory or heap memory. It does not matter. It only needs to outlive the lifetime of the function call.
Semantics of pointer parameters
When passing a unique_ptr to a function (by value), then your passing the responsibility to clean up memory to that function. When passing a shared_ptr or weak_ptr to a function, then that's saying "I'll possibly share memory ownership with that function or object it belongs to". That's quite different from passing a raw pointer, which implicitly mean "Here's a pointer. You can access it until you return (unless specified otherwise)".
Conclusion
If you have a function, then you usually know which kind of ownership semantics you have and 98% of the time you don't care about ownership and should just stick to raw pointers or even just references, if you know that the pointer you're passing is not a nullptr anyways. Callers that have smart pointers can use the p.get() member function or &*p, if they want to be more terse. Therefore, I would not recommend to template code to tackle your problem, since raw pointers give the caller all the flexibility you can get. Avoiding templates also allows you to put your implementation into an implementation file (and not into a header file).
To answer your concrete questions:
I don't see much value in adding this complexity. To the contrary: It complicates your code unnecessarily.
There is hardly any need for this. Even if you use std::dynamic_pointer_cast in the such, it is to maintain ownership in some way. However, adequate uses of this are rare, because most of the time just using dynamic_cast<U*>(ptr.get()) is all you need. That way you avoid the overhead of shared ownership management.
My preference would be: Use raw pointers. You get all the flexibility, intellisense and so forth and you will live happily ever after.
I would rather call this an antipattern - a pattern that should not be used. If you want to be generic, then use raw pointers (if they are nullable) or references, if the pointer parameter would never be a nullptr. This gives the caller all the flexibility while keeping the interface clean and simple.
Further reading: Herb Sutter talked about smart pointers as function parameters in his Guru of the Week #91. He explains the topic in depth there. Especially point 3 might be interesting to you.
After reviewing some more material, I've finally decided to use plain old raw pointers in my public interface. Here is the reasoning:
We shouldn't be designing interface to accommodate bad design decisions of others. The mantra of "avoid raw pointers like a plague and replace them with smart pointers everywhere" is just bad advice (also se Shutter's GoTW). Trying to support those bad decisions spreads them in to your own code.
Raw pointers explicitly sets up contract with callers that they are the one who need to worry about lifetime of inputs.
Raw pointers gives the maximum flexibility to callers who have shared_ptr, unique_ptr or just raw pointers.
Code now looks much more readable, intuitive and reasonable unlike those duck typed templates taking over everywhere.
I get my strong typing back along with intellisense and better compile time checks.
Casting up and down hierarchy is a breeze and don't have to worry about perf implications where new instance of smart pointer may get created at each cast.
While passing pointers around internally, I don't have to carefully care if the pointer would be shared_ptr or raw pointer.
Although I don't care about it, there is better pathway to support older compilers.
In short, trying to accommodate potential clients who have taken up on guidelines of never using raw pointers and replace them with smart pointers everywhere causes polluting my code with unnecessary complexity. So keep simple things simple and just use raw pointers unless you explicitly want ownership.

Use of raw pointers in modern C++ post C++11 [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
What are some of the main reasons to use raw pointers in 2014, given that the C++11 standard is now well supported by most decent compilers?
I identified a couple of scenarios :
You are extending a legacy codebase that makes heavy use of raw pointers, and you would like to maintain consistency in style.
You are using a library that only exports raw pointers, but I guess you could still make use of casts.
You want to exploit pointers's capability to provide multiple levels of indirection. (I do not know C++11 well enough to know if this can be achieved using smart pointers, or using some other techniques.)
What other scenarios do you think are appropriate for use of pointers?
Would you even recommending learning about pointers in general, today?
I can imagine circumstances where you have a statically-allocated array and you want to use a raw pointer to iterate through it in high-performance code. There's still nothing wrong with this.
Your #1 is true.
Your #2 is possibly not right: if you're "making use of casts" to transform raw pointers owned by a third-party library, into smart pointers (implying local ownership) then something has gone horribly wrong.
Your #3 is technically true but avoid this whenever you can.
What is not recommended nowadays is playing with raw pointers to your own, dynamically-allocated memory. That is, the advice is to avoid new without smart pointers (and the corollary is that you shouldn't need delete).
Everybody is against raw pointers as it's way too easy to leak them.
But you can use raw pointers to point to data owned somewhere else... just don't new/delete them. Use std::unique_ptr or std::shared_ptr for that. Or for dumb (POD) memory buffers use std::vector<unsigned char>, don't malloc and free yourself.
Think of a std::vector<heavy_object*> when you need to juggle with sub-selections of objects that are non-trivial to copy but already exist elsewhere. You need pointers for this.
You also need pointers in functions for optional arguments where references don't cut it as you want to be able to pass a nullptr.
Pointers to consecutive objects can also be iterated easily without any std::iterator overhead. Just ++ or -- and that's it. I often use direct pointer iteration instead of begin, end for vectors.
As you understand how they work... you'll need them a lot and you'll use them properly.
Smart pointers are used for handling object ownership issues, but not all pointers are used to deal with object ownership. For example it makes more sense to pass raw pointer to a function if you are not planning to pass ownership to this function (i.e. you just want the function to deal with the data addressed by the pointer)
IMHO Raw pointers still have their place.
What C++11 gives us is the ability to manage the lifespan of raw pointers so that we don't have to delete them ourselves.
There is nothing wrong with using raw pointers as long as they are managed by a smart pointer/pointer manager in the correct scope or frame to ensure their lifespan is correct. If that is true then you never have to delete a raw pointer and you can safely use them within the scope/frame throughout which their life-time is guaranteed.
I would say, if possible, store a raw pointer to your new object in a std::unique_ptr if its lifespan should be controlled by a given scope/frame. Once that is done use the raw pointer within that scope frame. Just never delete it;
Sometimes it is not possible to manage the lifespan of a new object from a single scope or frame. In this case use a std::shared_ptr in every scope/frame that independently needs to manage the lifespan of the new object. Then, within each scope/frame, there is no reason not to use the raw-pointer just like when it is being managed by a std::unique_ptr.
So there is often no reason to incur the speed disadvantage of smart pointers as one of their strengths lies in managing the life-span of the new object in order to ensure the validity of the raw-pointer and the automatic destruction of its object when its no longer needed.
There are other times when a raw pointer is not appropriate.
For example when a managed pointer needs to transfer "ownership" to another scope/frame. That is when you need the scope/frame responsible for managing the life-span of the new object to change. In these cases avoid raw pointers like the plague!
What other scenarios do you think are appropriate for use of pointers?
One of the main scenarios in which raw pointers are used is when you have non-owning pointers. Typically, where a reference would work, but you want to avoid the constraints of a reference (non-reseatable, non-copyable). You could use a reference_wrapper type in those cases, but it's simpler to just use a raw pointer instead. Smart-pointers encode ownership (who creates and destroys the object), so, if there is no ownership to encode (because it is implied otherwise), then a raw pointer is OK.
Just to make it clear, typical examples of what I just explained are things like:
temporary copyable functors that need a pointer to some object that it doesn't own.
internal cross-links within a data structure (e.g., "back pointers").
But it's important to notice that these things should not, in general, be present in interfaces. Generally, you can avoid raw pointers pretty much completely in interfaces (e.g., library functions and classes), and only really use them internally, i.e., in library-side code, not in user-side code. In other words, if you need to use raw pointers, hide them away.
Raw pointers are also sometimes seen for optional function parameters, where you can pass in a nullptr if you don't want that result.
The main thing that should be avoided, and can be avoided in general, is naked new / delete calls in user-side code. A typical good modern C++ library (and even more so with C++11) will not have any such naked new / delete occurrences, and that's a fact.
Raw pointers are not so much a problem by themselves, what is problematic is (1) manual memory management, and (2) ownership management (which is problematic if raw pointers are used instead of smart-pointers).
Would you even recommending learning about pointers in general, today?
Of course you should learn about pointers. They are essential to understanding programming, and to learning to write library-side code. Raw pointers are still very present in the guts of a lot of library code and such, even if you don't see them.
common reasons to use raw pointers off the top of my head.
Reading and parsing binary files
Interacting directly with hardware
Arrays?
Speed. AFAIK Smart pointers are slower than raw pointers and there are relatively safe ways to use raw pointers. See Chromium's code base for example or WebKit's. Both use various kinds of tracked memory without the full overhead of smart pointers. Of course with limitations as well.

When to use C++ pointers in game development

I've looked at a bunch of articles, and most tell the same story: don't use pointers unless you have to. Coming from a C#/Java background where memory is all managed, I have absolutely no idea when it's appropriate to use a pointer, except for these situations:
dynamic memory (like variable-size arrays)
polymorphism
When else would I use pointers, especially in the context of gamedev?
"Don't use pointers, they're slow" doesn't make sense (at least not in C++).
It's exactly like saying, "Don't use variables, they're slow".
Did you mean, "Don't use dynamic memory allocation"?
If so: I don't think you should worry about it right now. Write the code first, then optimize later.
Or did you mean to say, "Don't use raw pointers (i.e. of type foo*)", which would require new and delete?
If so, that is good advice: You generally want smart pointers instead, like shared_ptr or unique_ptr, to manage objects, instead of dealing with raw pointers. You shouldn't need to use new and delete in most C++ code, even though that might seem natural.
But they're still pointers under the hood!
Or did you mean something else?
Addendum
Thanks to the #bames53 below for pointing this out:
If passing a copy is an option (i.e. when you're passing small amounts of data, not a huge structure or an array that could be larger than a few registers, e.g. on the order of ~16 bytes), do not use pointers (or references) to pass data; pass by copy instead. It allows the compiler to optimize better that way.
The idea is that you don't want to have memory leaks, nor slow down the program while retrieving memory, so, if you pre-allocate the structures you will need, then you can use pointers to pass the structures around, as that will be faster than copying structures.
I think you are just confused as to why pointers may be considered bad, as there are many places to use them, you just need to think about why you are doing it.
One primary use of pointers (although references are generally better when possible), is to be able to pass an object around without copying it. If an object contains a lot of data, copying it could be quite expensive and unnecessary. In terms of game development, you can store pointers in a container like a std::vector so you can manage objects in a game. For instance, you could have a vector that contains pointers to all enemies in the game so you can perform some "mass procedure" on them. It might be worthwhile to look into smart pointers, too, since these could make your life a lot easier (they help a great deal when it comes to preventing memory leaks).
You don't need pointers for variable size arrays, you can (and usually should) use std::vector instead. You don't need raw pointers for polymorphism either; virtual functions work with smart pointers like unique_ptr.
In modern C++ you rarely need pointers. Often they will be hidden away inside resource owning classes like vectors. To pass objects around without copying them you can use references instead. Most of the remaining uses of pointers are covered by smart pointers. Very rarely you will want a 'non-owning' pointer, in which case raw pointers are fine.
You'll learn the appropriate uses of pointers if you learn about the things to should use instead of pointers. So learn about RAII, references, and smart_pointers.

Accelerated C++: Can I substitute raw pointers for smart pointers?

I love this book, sadly it does not cover smart pointers as they were not part of the standard back then. So when reading the book can I fairly substitute every mentioned pointer by a smart pointer, respectively reference?
"Smart Pointer" is a bit of a misnomer. The "smart" part is that they will do some things for you, whether or not you need, want, or even understand what those things are. And that's really important. Because sometimes you'll want to go to the store, and smart pointers will drive you to church. Smart pointers solve some very specific problems. Many would argue that if you think you need smart pointers, then you're probably solving the wrong problem. I personally try not to take sides. Instead, I use a toolbox metaphor - you need to really understand the problem you're solving, and the tools that you have at your disposal. Only then can you remotely expect to select the right tool for the job. Best of luck, and keep questioning!
Well, there are different kinds of smart pointers. For example:
You could create a scoped_ptr class, which would be useful when you're allocating for a task within a block of code, and you want the resource to be freed automatically when it runs of of scope.
Something like:
template <typename T>
class scoped_ptr
{
public:
scoped_ptr(T* p = 0) : mPtr(p) {}
~scoped_ptr() { delete mPtr; }
//...
};
Additionally you could create a shared_ptr who acts the same but keeps a ref count. Once the ref count reach 0 you deallocate.
shared_ptr would be useful for pointers stored in STL containers and the like.
So yes, you could use smart pointers for most of the purposes of your program.
But think judiciously about what kind of smart pointer you need and why.
Do not simply "find and replace" all the pointers you come across.
No.
Pointers which represent object ownership should be replaced by smart pointers.
Other pointers should be replaced by iterators (which in the simplest case is just a typedef for a raw pointer, but no one would think they need to delete).
And of course, the implementation code for smart pointers and iterators will continue to need raw pointers.