Questions about auto_ptr

Hello, I have been coding a game client for probably a few months now and I just recently decided to switch to auto_ptr's to save myself any errors in the future. I have read up on them and know what they're used for but I am kind've confused on where you should use them and when it's safe to just use a raw pointer.

I don't have the best concept on how pointers work, but I know the basics and I would like to see if this code would be safe:
1
2
3
4
5
6
7
8
9
10
11
12
13
void main()
{
    MyClass *mine = new MyClass();
    function(mine);
    return 0;
}

void function(MyClass *mine)
{
    std::auto_ptr<MyClass> theClass(mine);
    // Code goes here
    // It should delete the memory itself since it's not being used anywhere
}


Now, as far as I know, mine shouldn't have to be deleted since it's still being pointed to an object. Would it be more effecient to pass a auto_ptr through function since it won't have to copy it, it can just transfer ownership?

I have read a few things on google that say not to put a auto_ptr in STL containers. Would that include doing something like this:
1
2
3
4
5
6
7
struct Test
{
    std::auto_ptr<SomeClass> theClass;
    // Other variables would go here
};

std::map<std::string, Test> theMap;

I have a code similar to this in my project and i've suddenly gotten an error about using map.insert. It popped up the stl_pair.h header as well.

Another problem that i'm having is base related. Not sure that I am able to use a auto_ptr here; I might have to use a raw one and then transfer it into one(like the first peice of code). Here's an example of what I mean:
1
2
3
4
5
6
7
8
9
class Base {};
class Derived : Base {}

void function1(std::auto_ptr<Base> base) {}
int main()
{
    std::auto_ptr<Derived> test(new Derived());
    function1(test); // This is where it fails. If I were to use raw pointers it would work fine
}


If someone could answer my questions then I would be greatly appreciative.
Last edited on
Ownership of objects pointed to by auto_ptr is transferable, but not shareable. This means that only one auto_ptr can be used to point to some object at any time. You point another auto_ptr to the same object and the old auto_ptr is automatically null-ed.

Particularly, with void function1(std::auto_ptr<Base> base) {} you are actually stating that the object passed to function1 should be deleted before the function returns.

There are two or three circumstances where auto_ptr is useful.

1. In the constructor of your class/struct:
1
2
3
4
struct A {
  auto_ptr<T> ptr;
  A() : ptr(new T()) { /*do whatever that may cause exception*/ }
}

This guarantees that if the exception is triggered in the constructor body, the object pointed by ptr will be deallocated. It also ensures that the object pointed by ptr is automatically deallocated in the destructor without extra code.
2. In function
1
2
3
4
5
void g(T*);
void f() {
  auto_ptr<T> ptr = new T();
  g(ptr.get());
}

This guarantees that if the function g throws exception, then the object pointed to by ptr will be deleted. Basically, protects against "multi-level returns". Also, it saves you the hassle of doing the deallocation manually in the end of the function, although you can always opt to do it earlier.
3. As return value from function (less useful though)
1
2
3
4
5
auto_ptr<T> f() {
  auto_ptr<T> ptr = new T();
  ...
  return ptr;
}


Objects pointed to by boost::shared_ptr can be .. you know, shared.

Regards

EDIT:
Now I see that I actually didn't answer your questions fully.

Regarding the conversion ambiguity that you get from your compiler. The following code will work with gcc:
1
2
3
4
5
6
7
8
9
10
class Base {};
class Derived : public Base {};

void function1(auto_ptr<Base> base) {}

int main()
{
    auto_ptr<Derived> test(new Derived());
    function1(static_cast< auto_ptr<Base> >(test));
}
The first obvious problem is that the inheritance in class-es (vs struct-s) is by default private and there is no implicit conversion sequence from Derived* to Base* in such case. Which is why it is necessary to specify the inheritance as public manually as I've done above. The second issue is that the auto_ptr template class has conversion operators and conversion constructors between all auto_ptr template instances. The operator and constructor conversions rank the same in this case, i.e. the conversion is ambiguous. What I cannot understand is why the use of static_cast (and function style cast and c-style cast) fixed the problem. Aren't they supposed to issue the same conversions in this case? I found out (using code traces) that the preferred method ends up being the templated auto_ptr constructor. Why?

As to why you shouldn't use auto_ptr in standard containers - because they expect that all copies of the objects they store (be pointers or not) to be effectively equivalent. A copy of an auto_ptr removes ownership from the original (and zeroes it), therefore violating this assumption.
Last edited on
Topic archived. No new replies allowed.