auto_ptr transfer of ownership behavior

Hello.

I apologize if this question has been asked before. Consider the following code:

#include <iostream>
#include <memory>

using namespace std;

class A {
public:
A() {}
~A() { cout << "A destructed" << endl; }
void print() { cout << "A::print called" << endl; }
};

class B {
public:
B(auto_ptr<A> a) : m_a(a) {}
auto_ptr<A> m_a;
};

int main() {
auto_ptr<A> a(new A);
{
B b(a);
}
a->print();
cout << "exiting" << endl;
}


Compiled with g++ 4.4.3 on Ubuntu.

Output is:
A destructed
A::print called
exiting

Why didn't this result in a segfault?
You're very lucky you got the segfault, or you might not have realised there was an error.

First, I should say, I don' think auto_ptr is helpful when used in this way. boost has shared_pointer which is probably what you want here.

When B is constructed, it passes ownership of pointer a to object b. When b is destroyed, it destroys a because it owns it.

When you call print on a, it's an error because a has already been destroyed.
It did *not* segfault. I want the ownership to pass to b, but apparently it did not. Take another look at the output.

Thanks,
Jeff
It did transfer ownership. It's just that the line

a->print();

does not require dereferencing of the "this" pointer to call the function or to execute it.
Thanks, jsmith for the Aha moment.

You're saying if A::print accessed an instance variable, it would segfault. The this pointer is null at a->print, but since it doesn't need it, the code executes fine.

Thanks again.
Jeff
It might segfault.

Accessing memory that is not allocated is undefined behavior according to the standard. Undefined
means exactly that -- it could do anything; it needn't necessarily segfault.
Thanks jsmith.

I'm still trying to get my head around auto_ptr behavior. Consider the following code:

#include <iostream>
#include <memory>

using namespace std;

class A {
public:
A() {}
~A() { cout << "A destructed" << endl; }
void print() { cout << "A::print called" << endl; }
};

class B {
public:
B(auto_ptr<A>& a) : m_a(a) {}
void print() { m_a->print(); }
auto_ptr<A> m_a;
};

class C : public A {
public:
void print() { cout << "C::print called" << endl; }
};

int main() {
auto_ptr<A> c(new C);
B b(c);
b.print();
cout << "exiting" << endl;
}

When this runs, the output is:

A::print called
exiting
A destructed

Why wasn't C::print() called? I think the term Scott Meyers uses is "slicing" in the Effective C++ book. But the underlying type is a pointer, why isn't it a pointer to C in this case?
Achhhhh.

print should have been virtual.

My mistake. Never mind.
Topic archived. No new replies allowed.