0

I am learning C++. I just learned std::shared_ptr can be used for managing heap-allocated object as in reference-counting manner.

Currently my compiler (Xcode/Clang/C++11) shows exact behavior what I wanted. Prints this result,

Step0
Step1
CREATED!
Step2
Step3
Step5
DESTROYED!
Step6

with this code.

class   Obj1
{
    public:
        Obj1() { printf("CREATED!\n"); }
        ~Obj1() { printf("DESTROYED!\n"); }
};

std::shared_ptr<Obj1> func1 ()
{
    printf("Step0\n");
    {
        printf("Step1\n");
        std::shared_ptr<Obj1>   o1(new Obj1());
        printf("Step2\n");
        std::shared_ptr<Obj1>   o2  =   o1;
        printf("Step3\n");
        return  o2;
    }
    printf("Step4\n");
}



int main(int argc, const char * argv[])
{
    {
        std::shared_ptr<Obj1>   o3  =   func1();
        printf("Step5\n");
    }
    printf("Step6\n");
    return 0;
}

But as far as I know, this can be happen by C++'s copy constructor optimization when the std::shared_ptr is assigned to new variable. (I am not sure the name...) If it is, the Obj1 instance maybe not guaranteed to be alive when it is being returned from the function, because actually the shared_ptr is destroyed and re-creared at caller semantically.

Of course all these are newbie's assumption. Please let me know what actually expected on object lifetime in this case.

PS. This is derived from my previous question: Good practice or convention for cleanup heap allocated object?

trincot
  • 317,000
  • 35
  • 244
  • 286
eonil
  • 83,476
  • 81
  • 317
  • 516
  • 1
    *"...this can be happen by C++'s copy constructor optimization when the std::shared_ptr is assigned to new variable."* - You mean when `o2` in `func1()` is copied to `o3` in `main()`? *"(I am not sure the name...)"* - Do you also mean **R** eturn-**V** alue **O** ptimization? – Mark Garcia Feb 28 '13 at 03:57
  • @MarkGarcia Currently I think `o3` is newly created by copying `o2`. And I am not sure the reference count can be dropped to `0` at function borderline. That's the question... – eonil Feb 28 '13 at 04:02
  • @MarkGarcia And I think that's RVO. I couldn't figure out the name. Thanks. – eonil Feb 28 '13 at 04:03
  • 2
    The language would be unusable if it worked the way you fear. If the RVO doesn't happen then the object inside the function gets destroyed _after_ another copy has been made, so the `Obj1` gets kept alive by the new copy – Jonathan Wakely Feb 28 '13 at 18:38

2 Answers2

4

Either o2's lifetime is extended or a copy of it is made before it's destroyed. Either way, at least one shared_ptr always exists, so the code is safe.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Can I sure this is guaranteed by C++ semantics, not by a side-effect of optimization? – eonil Feb 28 '13 at 04:05
  • 3
    @Eonil The standard is formed by brilliant people (though they like undefined behaviors too much). They have scrutinized (almost) every possible usage scenarios for these things. Rest assured. You are in safe hands. – Mark Garcia Feb 28 '13 at 04:09
  • 1
    @Eonil: It is guaranteed that one of those two things will happen and both of them are safe. – David Schwartz Feb 28 '13 at 04:42
4

You misunderstand how that optimization works. Lets say we have small example:

std::shared_ptr<Foo> func()
{
    std::shared_ptr o2;
    o2.reset( new Foo  );
    return o2;
}
std::shared_ptr<Foo> o1 = func();

What compiler can do by optimization would look like this (not exactly but will help to understand the idea):

void func( std::shared_ptr<Foo> &o2 )
{
    o2.reset( new Foo  );
}
std::shared_ptr<Foo> o1;
func( o1 );

So from your point of view almost nothing changed, only copy of object (smart pointer) is eliminated. It would not affect lifetime of Foo.

Slava
  • 43,454
  • 1
  • 47
  • 90