-1

I don't understand why the destructor was called (the place of this call in the code below )

and if the destructor was called, why the function Print() could be called?

The code:

class Entity
{
public:
Entity()
{
    std::cout << "Ctor Call" << std::endl;
}

~Entity()
{
    std::cout << "Destroy Call" << std::endl;
}

void Print()
{
    std::cout << "Print me" << std::endl;
}
};

int main()
{    
Entity* ent;
{
    std::shared_ptr<Entity>sharedPtr = std::make_shared<Entity>();

    sharedPtr->Print();

    ent = &(*sharedPtr);

}   //after this line the destructor  was call 

ent->Print();     // the print is success 


std::cin.get();
}
AAEM
  • 1,837
  • 2
  • 18
  • 26
Yanshof
  • 9,659
  • 21
  • 95
  • 195
  • 1
    Because the scope ends, and this is the only `std::shared_ptr` that refers to the underlying object. The last `std::shared_ptr` that references this object gets destroyed, therefore the object gets destroyed and its destructor gets invoked. The fact that you have some other pointer pointing to the same object is irrelevant. This is precisely what `std::shared_ptr` is all about. That's how C++ works. – Sam Varshavchik Apr 15 '18 at 17:05
  • 1
    If you do stupid stuff like that, then you will have [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior), and that's really all there is to say about it. – Some programmer dude Apr 15 '18 at 17:08
  • 1
    you can get the same "weird" result with some simpler code:`Entity* ent = new Entity(); delete ent; ent->Print();` Or even, in your case, `Entity* ent = nullptr; ent->Print();` Very likely, this will get the same behaviour of your code using `shared_ptr. But as other are saying, you are in the realm of UB, so... everything can happen. Even that your code works somehow. But don't count on it. – Gian Paolo Apr 15 '18 at 17:55

3 Answers3

1

Yes, the destructor is called when the shared pointer goes out of scope (and thus gets destroyed itself). The reason that the subsequent Print() method call is successful is that calling a method on a destructed object is an undefined behaviour, so it doesn't need to necessarily crash. The object itself could still be lying around and the method call may be successful, albeit there is absolutely no guarantee. In this case the chances are even a bit higher because the method doesn't actually use any data from the instance, but simply calls library functions.

Please note that here copying the underlying address held by the shared_ptr doesn't make it increase its internal reference count, because this is done circumventing the "official" means of getting a copy from the shared pointer, in fact, from the std::shared_ptr reference:

shared_ptr objects can only share ownership by copying their value: If two shared_ptr are constructed (or made) from the same (non-shared_ptr) pointer, they will both be owning the pointer without sharing it, causing potential access problems when one of them releases it (deleting its managed object) and leaving the other pointing to an invalid location.

If the copy was obtained by copying the shared_ptr, then the object would not have been deleted.

Marco Pantaleoni
  • 2,529
  • 15
  • 14
  • from what i learn - the shared pointer is not end ( D`tor) in this case because of reference counter – Yanshof Apr 15 '18 at 18:14
1

why the function Print called without crash

Because there is no guarantee that if your code produce Undefined Behavior (and your does indeed) then it has to crash. It could even look that your program succeded and that is probably the worst side of UB.

Slava
  • 43,454
  • 1
  • 47
  • 90
1

The destructor was called because the object ent was created inside a local scope, so after going out of scope, the destructor should be called. For more informatoin about the shared pointers you may refer to this question

AAEM
  • 1,837
  • 2
  • 18
  • 26