std::auto_ptr<T> Usage - c++

I've read a reasonable amount in decent textbooks about the auto_ptr class. While I understand what it is, and how it gets you around the problem of getting exceptions in places like constructors, I am having trouble figuring out when someone would actually use it.
An auto_ptr can only hold a single type (no array new[] initialization is supported). It changes ownership when you pass it into functions or try and duplicate it (it's not a reference counting smart pointer).
What is a realistic usage scenario for this class give its limitations? It seems like most of the textbook examples of its use are reaching because there isn't even a reason to be using a pointer over a stack variable in most of the cases...
Anyway, I'll stop my rant - but if you can provide a short example/description or a link to a good usage scenario for this I'd be grateful. I just want to know where I should use it in practice in case I come across the situation - I like to practice what I learn so I remember it.

I'll give you a short example for a good usage. Consider this:
auto_ptr<SomeResource> some_function() {
auto_ptr<SomeResource> my_ptr = get_the_resource();
function_that_throws_an_exception();
return my_ptr;
}
The function that raises an exception would normally cause your pointer to be lost, and the object pointed to would not be deleted. With the auto_ptr this can't happen, since it is destroyed when it leaves the frame it was created, if it hasn't been assigned (for example with return).

auto_ptr has been deprecated in the now finalized C++11 standard. Some of the replacements are already available through TR1 or the Boost libraries. Examples are shared_ptr and unique_ptr (scoped_ptr in boost).

Related

understanding the smart pointer boost in c++

I am new to c++ as well as smart pointer.
I have a code like this.
Example* Example::get_instance() {
Example* example = new Example();
return example;
}
I am trying to convert it to smart pointer like this
shared_ptr<Example> Example::get_instance() {
shared_ptr<Example> example (new Example());
return example;
}
Is this the correct way because when i am trying to call this from another class its not working.I am trying to implement a singleton object.
You are creating a new Example object every time the object is requested, That is a memory leak, an you are also returning a different object every time. Try this instead:
Example & Example::get_instance() {
static Example example;
return example;
}
Also please note the following advices for your code:
when creating smart pointers prefer make_shared instead of shared_ptr<YourType>(new YourType(...)). The reason why can be found here. Relevant excerpt:
This function typically allocates memory for the T object and for the
shared_ptr's control block with a single memory allocation (it is a
non-binding requirement in the Standard). In contrast, the declaration
std::shared_ptr p(new T(Args...)) performs at least two memory
allocations, which may incur unnecessary overhead. Moreover,
f(shared_ptr(new int(42)), g()) can lead to memory leak if g
throws an exception. This problem doesn't exist if make_shared is
used.
understand the difference between std::unique_ptr and std::shared_ptr. For your case, a std::unique_ptr would have been better, but there is an even simpler solution to your problem, which I have shown above.
in general, avoid pointers when you can use references instead, they're easier to use and code looks a bit cleaner.
and finally, do you REALLY want a singleton? I just have to be ask. I've been working full-time as a programmer for almost 4 years now. Not that long, I know, but enough to have encountered the situation where I regretted that I or someone else used the Singleton pattern instead of passing the reference to my object down the call chain.
Try to avoid singletons, you may later find your code using the singleton might in the end want to work on multiple instances of your Example object instead of calling Example::get_instance and only work on that single instances. So when you'll have that revelation, (and it might be only a matter of time), you'll have major refactoring ahead of you.
So, "Beware, there be dragons!".

How to return smart pointers (shared_ptr), by reference or by value?

Let's say I have a class with a method that returns a shared_ptr.
What are the possible benefits and drawbacks of returning it by reference or by value?
Two possible clues:
Early object destruction. If I return the shared_ptr by (const) reference, the reference counter is not incremented, so I incur the risk of having the object deleted when it goes out of scope in another context (e.g. another thread). Is this correct? What if the environment is single-threaded, can this situation happen as well?
Cost. Pass-by-value is certainly not free. Is it worth avoiding it whenever possible?
Thanks everybody.
Return smart pointers by value.
As you've said, if you return it by reference, you won't properly increment the reference count, which opens up the risk of deleting something at the improper time. That alone should be enough reason to not return by reference. Interfaces should be robust.
The cost concern is nowadays moot thanks to return value optimization (RVO), so you won't incur a increment-increment-decrement sequence or something like that in modern compilers. So the best way to return a shared_ptr is to simply return by value:
shared_ptr<T> Foo()
{
return shared_ptr<T>(/* acquire something */);
};
This is a dead-obvious RVO opportunity for modern C++ compilers. I know for a fact that Visual C++ compilers implement RVO even when all optimizations are turned off. And with C++11's move semantics, this concern is even less relevant. (But the only way to be sure is to profile and experiment.)
If you're still not convinced, Dave Abrahams has an article that makes an argument for returning by value. I reproduce a snippet here; I highly recommend that you go read the entire article:
Be honest: how does the following code make you feel?
std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();
Frankly, even though I should know better, it makes me nervous. In principle, when get_names()
returns, we have to copy a vector of strings. Then, we need to copy it again when we initialize
names, and we need to destroy the first copy. If there are N strings in the vector, each copy
could require as many as N+1 memory allocations and a whole slew of cache-unfriendly data accesses > as the string contents are copied.
Rather than confront that sort of anxiety, I’ve often fallen back on pass-by-reference to avoid
needless copies:
get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );
Unfortunately, this approach is far from ideal.
The code grew by 150%
We’ve had to drop const-ness because we’re mutating names.
As functional programmers like to remind us, mutation makes code more complex to reason about by undermining referential transparency and equational reasoning.
We no longer have strict value semantics for names.
But is it really necessary to mess up our code in this way to gain efficiency? Fortunately, the answer turns out to be no (and especially not if you are using C++0x).
Regarding any smart pointer (not just shared_ptr), I don't think it's ever acceptable to return a reference to one, and I would be very hesitant to pass them around by reference or raw pointer. Why? Because you cannot be certain that it will not be shallow-copied via a reference later. Your first point defines the reason why this should be a concern. This can happen even in a single-threaded environment. You don't need concurrent access to data to put bad copy semantics in your programs. You don't really control what your users do with the pointer once you pass it off, so don't encourage misuse giving your API users enough rope to hang themselves.
Secondly, look at your smart pointer's implementation, if possible. Construction and destruction should be darn close to negligible. If this overhead isn't acceptable, then don't use a smart pointer! But beyond this, you will also need to examine the concurrency architecture that you've got, because mutually exclusive access to the mechanism that tracks the uses of the pointer is going to slow you down more than mere construction of the shared_ptr object.
Edit, 3 years later: with the advent of the more modern features in C++, I would tweak my answer to be more accepting of cases when you've simply written a lambda that never lives outside of the calling function's scope, and isn't copied somewhere else. Here, if you wanted to save the very minimal overhead of copying a shared pointer, it would be fair and safe. Why? Because you can guarantee that the reference will never be mis-used.

C++: Safe to use locals of caller in function?

I think it's best if I describe the situation using a code example:
int MyFuncA()
{
MyClass someInstance;
//<Work with and fill someInstance...>
MyFuncB( &someInstance )
}
int MyFuncB( MyClass* instance )
{
//Do anything you could imagine with instance, *except*:
//* Allowing references to it or any of it's data members to escape this function
//* Freeing anything the class will free in it's destructor, including itself
instance->DoThis();
instance->ModifyThat();
}
And here come my straightforward questions:
Is the above concept guranteed, by C and C++ standards, to work as expected? Why (not)?
Is this considered doing this, sparingly and with care, bad practice?
Is the above concept guranteed, by C and C++ standards, to work as expected? Why (not)?
Yes, it will work as expected. someInstance is available through the scope of MyFuncA. The call to MyFuncB is within that scope.
Is this considered doing this, sparingly and with care, bad practice?
Don't see why.
I don't see any problem in actually using the pointer you were passed to call functions on the object. As long as you call public methods of MyClass, everything remains valid C/C++.
The actual instance you create at the beginning of MyFuncA() will get destroyed at the end of MyFuncA(), and you are guaranteed that the instance will remain valid for the whole execution of MyFuncB() because someInstance is still valid in the scope of MyFuncA().
Yes it will work. It does not matter if the pointer you pass into MyFuncB is on the stack or on the heap (in this specific case).
In regards for the bad practice part you can probably argue both ways. In general it's bad I think because if for any reason any object which is living outside of MyFuncA gets hold of the object reference then it will die a horrible death later on and cause sometime very hard to track bugs. It rewally depends how extensive the usage of the object becomes in MyFuncB. Especially when it starts involving another 3rd class it can get messy.
Others have answered the basic question, with "yeah, that's legal". And in the absence of greater architecture it is hard to call it good or bad practice. But I'll try and wax philosophical on the broader question you seem to be picking up about pointers, object lifetimes, and expectations across function calls...
In the C++ language, there's no built-in way to pass a pointer to a function and "enforce" that it won't stow that away after the call is complete. And since C++ pointers are "weak references" by default, the objects pointed to may disappear out from under someone you pass it to.
But explicitly weak pointer abstractions do exist, for instance in Qt:
http://doc.qt.nokia.com/latest/qweakpointer.html
These are designed to specifically encode the "paranoia" to the recipient that the object it is holding onto can disappear out from under it. Anyone dereferencing one sort of realizes something is up, and they have to take the proper cautions under the design contract.
Additionally, abstractions like shared pointer exist which signal a different understanding to the recipient. Passing them one of those gives them the right to keep the object alive as long as they want, giving you something like garbage collection:
http://doc.qt.nokia.com/4.7-snapshot/qsharedpointer.html
These are only some options. But in the most general sense, if you come up with any interesting invariant for the lifetimes of your object...consider not passing raw pointers. Instead pass some pointer-wrapping class that embodies and documents the rules of the "game" in your architecture.
(One of major the reasons to use C++ instead of other languages is the wealth of tools you have to do cool things like that, without too much runtime cost!)
i don't think there should be any problem with that barring, as you say, something that frees the object, or otherwise trashes its state. i think whatever unexpected things happen would not have anything to do with using the class this way. (nothing in life is guaranteed of course, but classes are intended to be passed around and operated on, whether it's a local variable or otherwise i do not believe is relevant.)
the one thing you would not be able to do is keep a reference to the class after it goes out of scope when MyFuncA() returns, but that's just the nature of the scoping rules.

Is there any reason to use auto_ptr?

After reading Jossutis' explanation on auto_ptr from his STL book I've got a strong impression that whatever task I would try to use it in I'd 100% fail becuase of one of many auto_ptr's pitfalls.
My question is: are there any real life tasks where auto_ptr is really usefull and does fit there well?
Clearly, auto_ptr looses against unique_ptr.
Now, in a 'strict C++03 without boost' world, I use auto_ptr quite often, most notably :
For 'factory member functions' which return a dynamically allocated instance of a given type : I like the fact that using std::auto_ptr in the return type explicits that the object must be deleted
In functions which allocate an object before attempting to insert it in a container afterwards : for example in order to release() only if std::map<>::insert returns that insertion succeeded
In a thread procedure which pops elements from a message queue, I like storing the pop'ed element in a const std::auto_ptr to make it clear that the message will be destroyed no matter what.
I would say it can be used, but it is not the best option.
First, it is a matter of year or less and auto_ptr is officially deprecated. Second, there is a superior alternative: unique_ptr. Dr. Stroustrup once said about unique_ptr:
“What auto_ptr should have been” (but
that we couldn't write in C++98)
So unless you don't have the choice, auto_ptr is not a good choice. Mainly, because most C++ compilers these days implement move semantics and provide unique_ptr.
In simple scenarios when you need to temporarily control a heap-allocated object auto_ptr can be used without problems. For example if you need to conditionally create an object that will be used only within one function you can't allocate it on stack and auto_ptr lets you not care of the object lifetime should an exception occur.
I use std::auto_ptr moderately often, to ensure exception safety. That is, to prevent a memory leak in the event of part of a method throwing an exception.
For example:
Foo &Container::addFoo(
const std::string &name
)
{
// The post conditions of the method require that the new Foo
// has been added to this container, but the addition method
// may throw exceptiona
std::auto_ptr< Foo > foo(new Foo(name));
foo->twiddle();// may throw
this->addFoo(*foo);// record reference. May throw
return *foo.release();
}
Edited:
clarified that this->addFoo(*foo) records a reference.

Is this a fine std::auto_ptr<> use case?

Please suppose I have a function that accepts a pointer as a parameter. This function can throw an exception, as it uses std::vector<>::push_back() to manage the lifecycle of this pointer. If I declare it like this:
void manage(T *ptr);
and call it like this:
manage(new T());
if it throws an exception pushing the pointer into the std::vector<>, I effectively have got a memory leak, haven't I?
Would declaring the function like this:
void manage(std::auto_ptr<T> ptr);
solve my problem?
I would expect it to first allocate the std::auto_ptr on the stack (something that I guess couldn't ever throw an exception) and let it acquire ownership over the pointer. Safe.
Then, inside the function, I would push the raw pointer into the std::vector<>, which is also safe: if this fails, the pointer will not be added, but the smart pointer will still be owning the pointer so it will be destroyed. If the pushing succeeds, I would remove the smart pointer's ownership over that pointer and return: this can't throw an exception, so it will always be fine.
Are my theories correct?
-- Edit --
No, I think I can't do that. Doing that would require taking a non-const reference to rvalue (to take away ownership from the smart pointer). I would have to write
std::auto_ptr<T> ptr(new T());
manage(ptr);
for that to work, something that's quite inconvient in my case. I'm writing this so that I can implement RAII without polluting much the code. Doing that thing would not help, then. That would be catch 22.
-- Edit 2 --
Pulling what Jason Orendorff said down there here for quick reference by readers, the ultimate solution seems to be the following:
void manage(T *ptr)
{
std::auto_ptr<T> autoPtr(ptr);
vector.push_back(ptr);
autoPtr.release();
}
This solves the problem of the useless non-const reference to rvalue.
When I finish this class I'm coding I'll post it back here in case anyone finds it useful.
-- Edit 3 --
Ok, there has been a lot of discussion here, and there are key points that I should have clarified before. In general, when I post at stackoverflow, I try to explain the reason behind my questions and, in general, that is completely useless. So this time I thought I should go straight to the point. Turns out it didn't work quite well XD
Unfortunately my brain is deadlocking now, so I think I won't even be able to explain correctly what I first thought to accomplish my goals. I am trying to find a good solution for atomic operations and exception-safe code writing that fits lots of cases, but really, I can't handle it XD I think this is the kind of thing I will only master with time.
I am a really new C++ programmer and my focus is game development. When an exception is thrown in a game engine, it is the end of execution. The system will free all the memory for my process, so it doesn't really matter if one or two pointers leak here and there. Now that I am developing a server application, I'm finding it hard to deal with exceptions, because an exception can't crash the server; it must "crash the request".
That is, "Well, client, unfortunately the developers didn't foresee this condition, so you'll have to try it later (up to here, it is basically the same thing as with a game engine, nothing is being repared, only it is isolated to the context of just a request, and not the whole process). But don't panic, as everything was left in a valid state (here is one of the differences, however. The process isn't terminated, so the operating system can't free the resources for you; furthermore, you have to pay attention to undo the operations so far, so that you don't lock completely an user's account, for example, or even a full service provided by the server).".
I will just code more and more and note down my problems so that I can write a better question next time. I wasn't prepared to ask this now, I'm really sorry.
Thanks a lot for your replies, I really like stackoverflow. It is absolutely amazing how fast my questions are answered and how enlightening your answers are. Thanks.
You could do it this way, but you still have to cleanup in the event of an exception not being thrown, which seems a little onerous.
If you use something like boost::shared_ptr (I believe something like this is in TR1 libraries as well - as an example see MS's implementation) you could forget about having to cleanup in the event of things going as planned.
To make this work you would need to make your vector accept boost::shared_ptr < T > instance, then you would just let your original instance be cleaned up and it would leave instance in the vector alive in the case that all goes well. In the case things go wrong all boost::shared_ptr instances would be destroyed and you would still end up with no leak.
With smart pointers it's about picking one that suits the task, and in this case shared ownership (or simple ownership transfer) seems to be a goal so there are better candidates than std::auto_ptr on most platforms.
In general, using std::auto_ptr as a type of function argument unambiguously tells the caller that function will take ownership of the object, and will be responsible for deleting it. If your function fits that description, then by all means use auto_ptr there regardless of any other reason.
I think enough discussion has been generated to warrant yet another answer.
Firstly, to answer the actual question, yes, it is absolutely appropriate (and even necessary!) to pass an argument by smart pointer when ownership transfer occurs. Passing by a smart pointer is a common idiom to accomplish that.
void manage(std::auto_ptr<T> t) {
...
}
...
// The reader of this code clearly sees ownership transfer.
std::auto_ptr<T> t(new T);
manage(t);
Now, there is a very good reason why all smart pointers have explicit constructors. Consider the following function (mentally replace std::auto_ptr with boost::shared_ptr if it tickles your fancy):
void func(std::auto_ptr<Widget> w, const Gizmo& g) {
...
}
If std::auto_ptr had an implicit constructor, suddenly this code would compile:
func(new Widget(), gizmo);
What's wrong with it? Taking almost directly from "Effective C++", Item 17:
func(new Widget(), a_function_that_throws());
Because in C++ order of argument evaluation is undefined, you can very well have arguments evaluated in the following order: new Widget(), a_function_that_throws(), std::auto_ptr constructor. If a function throws, you have a leak.
Therefore all resources that will be released need to be wrapped upon construction in RAII classes before being passed into a function. This means all smart pointer have to be constructed before passing them as an argument to a function. Making smart pointers be copy-constructible with a const reference or implicitly-constructible would encourage unsafe code. Explicit construction enforces safer code.
Now, why shouldn't you do something like this?
void manage(T *ptr)
{
std::auto_ptr<T> autoPtr(ptr);
vector.push_back(ptr);
autoPtr.release();
}
As already mentioned, the interface idioms tell me that I can pass a pointer that I own and I get to delete it. So, nothing stops me from doing this:
T item;
manage(&t);
// or
manage(&t_class_member);
Which is disastrous, of course. But you'd say "of course I know what the interface means, I'd never use it that way". However you may want to add an extra argument to a function later. Or someone (not you, or you 3 years later) comes along this code, they may not see it the same way as you do.
This hypothetical "someone else" may only see a header without a comment and (rightly) presume the lack of ownership transfer.
They may see how this function is used in some other code and replicate the usage without looking at the header.
They may use code auto-completion to invoke a function and not read the comment or the function and presume the lack of ownership transfer.
They may write a function that wraps you manage function and yet someone else will use the wrapper function and will miss the documentation of the original function.
They may try to "extend" you code so that all the old code compiles (and automatically becomes unsafe):
void manage(T *t, const std::string tag = some_function_that_throws());
As you can see, explicit construction of a smart pointer makes it much harder to write unsafe code in the above cases.
Therefore, I would not recommend going against decades of C++ expertise to make perceivably "nicer" and "fun" API.
My 2c.
Yes, that's fine. (See edit below.) (jkp might be seeing something I've missed, but I don't think you "still have to clean up in the event of an exception being thrown" because, as you say, in that case the auto_ptr will delete the object for you.)
But I think it would be better still to hide the auto_ptr shenanigans from the caller:
void manage(T *t) {
std::auto_ptr<T> p(t); // to delete t in case push_back throws
vec.push_back(t);
p.release();
}
EDIT: I initially wrote "Yes, that's fine," referring to the original manage(auto_ptr<T>) plan, but I tried it and found that it doesn't work. The constructor auto_ptr<T>::auto_ptr(T *) is explicit. The compiler wouldn't let you write manage(new T) because it can't implicitly convert that pointer to an auto_ptr. manage(T *) is a friendlier interface anyway!