1

In C++, when passing an object by value, are there restrictions on when the copy takes place ?

I have the following code (simplified):

class A;
class Parent
{
public:
    void doSomething(std::auto_ptr<A> a); // meant to transfer ownership.
};

std::auto_ptr<A> a = ...;
a->getParent()->doSomething(a);

It acts like:

std::auto_ptr<A> a = ...;
std::auto_ptr<A> copy(a);
a->getParent()->doSomething(copy);

Which will obviously segfault since a is now referencing NULL.

And not like:

std::auto_ptr<A> a = ...;
Parent* p = a->getParent();
p->doSomething(a);

Is this expected ?

J.N.
  • 8,203
  • 3
  • 29
  • 39
  • 1
    See [this SO question](http://stackoverflow.com/questions/15166907/is-there-a-sequence-point-between-a-function-call-returning-an-object-and-a-meth). Basically, `getParent()` could be evaluated before or after the copy. – Jesse Good May 22 '13 at 05:09
  • I had looked for that but failed ... Thanks ! – J.N. May 22 '13 at 05:16

2 Answers2

0

A: auto_ptr is deprecated in newer versions of C++, I recommend checking out unique_ptr.

B: This behavior is expected. An auto_ptr owns the thing that it has created. So if you wish to properly transfer ownership from one auto_ptr to another, the original auto_ptrs managed object would properly be a null pointer. Though I believe this logic is handled by the std::auto_ptr library and you shouldn't have to do anything special to get this behavior. If two auto_ptrs were allowed to manage the same object, they would also both try and free the memory for this object when they went out of scope. This is bad in itself, but even worse, is that if one of these auto_ptrs had broader scope it could attempt to reference memory that no longer held the object in question because it had since been freed by the other auto_ptr and in this we have true chaos. Hence, when ownership is transferred, the original pointers managed object is set to null, and we have the illusion of safety. :)

MobA11y
  • 18,425
  • 3
  • 49
  • 76
  • My question is when does the copy happen ? I know the ownership is transferred (that's why it's being used in the first place). I'd use unique_ptr but I am stuck with C++03 for a while (as mentionned in the tags). – J.N. May 22 '13 at 04:43
  • Can you expand on "when does the copy happen" and what you mean by that? Are you referring to when auto_ptr a transfers ownership and becomes null? – MobA11y May 22 '13 at 13:34
  • Yes. I am talking about the sequencing of the operations when written in one statement. Look for "sequence point" in C++. They've disappeared from C++11, but the notion of sequencing hasn't. It's kind of problem that says that `++i + ++i` is undefined behaviour. – J.N. May 23 '13 at 00:07
0

From my point of view, the example is not good because of at least three reasons.

1) Looking at the code without seeing doSomething proto it is not clear that the ownership can change.

2) If by a slightest chance the result can depend on the order of evaluation, the code is not portable or implementation dependent and so not acceptable.

3) Even if the order of evaluation is right, the code can raise this exact question from other developers and will waste their time. The readability must be of the highest priority.

jackua
  • 16
  • 3
  • 1) When working with auto_ptr you MEAN that the ownership can change. That hasn't changed with C++11 and unique_ptr. 2) Yes that was my question, I was asking if there was anything I could rely on or not. I can't, so the code is not good. 3) I worked with talented people though they tend to abuse auto_ptr ;) – J.N. May 22 '13 at 09:08
  • 1) yes, can change but better in a predictable way, in a separate line and not in parameter evaluation. we are stuck with older gcc but we added -std=c++0x to get at least a little of new C++ and we enjoy unique_ptr and shared_ptr. – jackua May 22 '13 at 15:33
  • jackua: I know GCC options. In large company you just can't change how the code is being compiled (I agree that's sad, but cold, hard reality). Besides, std::auto_ptr is very much predictable because you know the type of the variable you're dealing with. Especially when it's used everywhere in the codebase. – J.N. May 23 '13 at 00:06
  • J.N: Depends on what "large" means. Agree that this is not simple. It took many months to convince config group that we needed it, help to fix build failures. I touched a few dozens files out of 5K affected. IDEs and tools failed. I reported problems to Coverity, Oracle Studio, NetBeans. Dbx on Linux and NetBeans released updates. I created a list of new features available on gcc 4.4.5 :(. After 2+ months we got no problems @ loading new libs with others compiled with older gcc and w/o c++0x. It was right call. BTW, auto_ptr was the only place that needed brain to update :). – jackua May 23 '13 at 17:14