-4
class Person
{
public:
    string s;
    ~Person(){ cout << "Destructor" << endl; }
};
void _Person(Person a){ cout << a.s << endl; }
auto main() ->int
{
    unique_ptr<Person> p{new Person()};
    _Person(*p); 
    cout << "New Line" << endl;
   return 0;
}

output:

Destructor
New Line
Destructor

why printed "Destructor" two times?

clcto
  • 9,530
  • 20
  • 42

2 Answers2

3

Because you create two Person objects in your code.

Take a look at this explanation at your code:

class Person // declare a class Person
{
public:
    string s;
    ~Person(){ cout << "Destructor" << endl; }
};

// function that takes a class Person as argument
void _Person(Person a) {
  cout << a.s << endl;
}


auto main() ->int
{
    unique_ptr<Person> p{new Person()}; // creation of one instance
    _Person(*p);                        // creation of second instance,
    // because p is passed by value, which means that the default copy constructor of the
    // class Person is activated, thus another object is created!!

    // when the function you called terminates, the copy goes out of scope,
    //thus ~Person() is called
    cout << "New Line" << endl;
    return 0;
}
// the object you created by new, now goes out of scope and gets deleted,
//thus ~Person() is called

But unique_ptr allows us to create another object?

Of course. Check out the ref.

These pointers are unique for deleting the object.

[EDIT]

Take this into account:

A singleton ensures only one instance of a type.

A unique_ptr ensures only one smart pointer to any instance.

Source

[EDIT.2]

Nice link from chris, which talks about the rules for using an underscore.

To be laconic, I would suggest to change this:

_Person()

to this

Person()

It's not a compilation mistake, it's just not common.

[EDIT.3]

Generally in C++, you can pass class objects as references, in order to avoid copying. Copying can take some time when the objects are instances of big classes.

So, I suggest that you change your function:

void Person(Person a) {
  cout << a.s << endl;
}

to this

void Person(Person& a) {
  cout << a.s << endl;
}

and run again your code. Can you guess what the output should be now? We pass the instance by reference, thus no copy constructor of Person is called.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
2

It is because your function

void _Person(Person a){ cout << a.s << endl; }

takes argument by value so a copy of the object is created.

auto main() ->int
{
    unique_ptr<Person> p{new Person()};
    _Person(*p);                // this calls a function _Person 
                                // with a copy of what p points to
                                // this copy dies at the end of function scope
    cout << "New Line" << endl; // its dctor has been just called
   return 0;
}                               // and now is called dctor for original variable 
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • Here it might be appropriate to mention the differences of `std::unique:ptr` and a singleton. – πάντα ῥεῖ May 20 '14 at 19:24
  • 1
    Done @πάνταῥεῖ, καλή παρατήρηση (good point). I know you are not Greek. :P It's nice to see that the private_data_public_channel followed my example on editing his answer to explain the behaviour. :) – gsamaras May 20 '14 at 19:27
  • @G.Samaras I am glad that you are happy but I haven't followed your example – 4pie0 May 20 '14 at 19:39
  • Still, happy for a nice explanation. +1 – gsamaras May 20 '14 at 19:40
  • @πάνταῥεῖ thank you and again kind ask for giving a reply [here](http://stackoverflow.com/a/23767278/1141471) in comments – 4pie0 May 20 '14 at 19:40
  • @privatedatapublicchannel2 I mentioned my point there. It was/is not appropriate to mention the singleton pattern as a possible solution for [this question](http://stackoverflow.com/questions/23767241/c-static-const-class-members-initialization). – πάντα ῥεῖ May 20 '14 at 19:45
  • @πάνταῥεῖ There is provided correct solution there. Moreover there is also showed how singleton can be used (but it is mentioned as possible but not preferred solution, because it has many pitfalls). You can consider undownvoting please – 4pie0 May 20 '14 at 19:56
  • @privatedatapublicchannel2 If any of the GoF patterns are in question there it's more about the [**Flyweight**](http://en.wikipedia.org/wiki/Flyweight_pattern) IMHO. Having certain `static const T` instances along with a certain class to give useful _common_ values like e.g. `ZERO`, `PI`or `NORMAL_MATRIX`, whatever, is a commonly used and valid technique. I hope you get my point now. I will of course leave the same comment on your answer over there. – πάντα ῥεῖ May 20 '14 at 20:00