Sort function calls destructor?

Pages: 12
I have a slight problem here.
Everything works fine until the part where my bunny objects should be sorted. But something happens when sort function is called and destructor is called for each object. What did I do wrong?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  #include <algorithm>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;


int GetRandom(int x){

    return rand()%x;
}

class Bunny
{

private:
    string F_names[5]={"Hajra","Mejra","Sefika","Hanifa","Zulfa"};
    string M_names[5]={"Wayne Rooney","Cristiano Ronaldo","Edin Dzeko","Robin Van Persie","Juan Mata"};
    string colors[4]={"white","brown","black","spotted"};
    bool Sex[2]={true, false};
    bool Vampire[2]={true, false};
    string name;
    string color;
    int age;
    bool isMale;
    string sex;
    bool isVampire;
    string VampireString;
    Bunny * POINTER;


public:


    Bunny()                                             //DEFAULT CONSTRUCTOR
    {
        int VVVAMP=GetRandom(100);
        age=0;
        color=colors[GetRandom(4)];
        if(VVVAMP==1 || VVVAMP==2){isVampire=true; VampireString="Radioactive vampire mutant";}
 else {isVampire=false;VampireString="normal";}
        isMale=Sex[GetRandom(2)];
        age=0;
        if(!isVampire){                     //IF VAMPIRE
            if(isMale)
            {
                name=M_names[ GetRandom(5)]; sex="Male";
                cout<< "Bunny "<<name<<" was born!"<<endl;
            }
            else
            {
                name=F_names[ GetRandom(5)]; sex="Female";
                cout<< "Bunny "<<name<<" was born!"<<endl;
            }
        }
        else                                //IF NOT VAMPIRE
        {
            if(isMale)
            {
                name=M_names[ GetRandom(5)]; sex="Male";
                cout<< "Radioactive mutant vampire bunny "<<name<<" was born!"<<endl;
            }
            else
            {
                name=F_names[ GetRandom(5)]; sex="Female";
                cout<< "Radioactive mutant vampire bunny "<<name<<" was born!"<<endl;
            }
        }
    }


    Bunny(string C)
    {                                                       //CONSTRUCTOR FOR CHILDREN
    int VVVAMP=GetRandom(100);
        age=0;
        color=C;
        if(VVVAMP==1 || VVVAMP==2){isVampire=true;} else {isVampire=false;}
        isMale=Sex[GetRandom(2)];
        age=0;
        if(!isVampire){                     
            if(isMale)
            {
                name=M_names[ GetRandom(5)]; sex="Male";
                cout<< "Bunny "<<name<<" was born!"<<endl;
            }
            else
            {
                name=F_names[ GetRandom(5)]; sex="Female";
                cout<< "Bunny "<<name<<" was born!"<<endl;
            }
        }
        else                                
        {
            if(isMale)
            {
                name=M_names[ GetRandom(5)]; sex="Male";
                cout<< "Radioactive mutant vampire bunny "<<name<<" was born!"<<endl;
            }
            else
            {
                name=F_names[ GetRandom(5)]; sex="Female";
                cout<< "Radioactive mutant vampire bunny "<<name<<" was born!"<<endl;
            }
        }
    }


    ~Bunny()                                                    //DESTRUCTOR
    {
        if(this->isVampire){cout<<"Radioactive mutant vampire bunny "<<this->getName()<<" died!"<<endl;}
        else{cout<<"Bunny "<<this->getName()<<" died!"<<endl;}
        POINTER=this;
        delete [] POINTER;
        POINTER=NULL;
    }
    bool getIsMale(){return isMale;}
    string getName(){return name;}
    string getSex(){return sex;}
    string getColor(){return color;}
    int getAge(){return age;}




    bool isMature()
    {
        if(  (age>=2) &&(isMale) ){return true;}
        return false;
    }

    void AddBabyToColony()
    {

    }

    void RemoveABunny()
    {

    }

    void PrintInfo()
    {
       /* for(int i=0;i<)*/
    }

};

    void ColonySort(Bunny** Colony,int x)    //THIS IS THE FUNCTION IM TALKING ABOUT
    {
        void order(Bunny** , Bunny **);

        for(int i=0; i<x ;i++)
        {
            for(int j=1; j<x; j++)
            {
                order(Colony+i, Colony+j);
            }
        }
    }

     void order(Bunny** pp1, Bunny** pp2)
     {

        if((*pp2)->getAge() > (*pp1)->getAge())
        {
            Bunny *PTR=*pp1;
            *pp1=*pp2;
            *pp2=PTR;

            delete[] PTR;
            PTR=NULL;
        }

     }

int main()
{
    bool MALE=false;
    int Males=0;
    int Females=0;
    int Total=5;
    srand(time(0));
    Bunny* BunnyColony=new Bunny[Total];


    for(int i=0; i<5; i++)
    {
        if(BunnyColony[i].getIsMale()){Males++;}
    }

    Females=5-Males;

    ColonySort(&BunnyColony,Total);          //HERE I CALL THE SORT FUNCTION

    cout<<"Bunny "<< BunnyColony[0].getName()<<" is " <<BunnyColony[0].getAge()<< " year's old."<<endl;
    cout<<"Bunny "<< BunnyColony[1].getName()<<" is " <<BunnyColony[1].getAge()<< " year's old."<<endl;
    cout<<"Bunny "<< BunnyColony[2].getName()<<" is " <<BunnyColony[2].getAge()<< " year's old."<<endl;
    cout<<"Bunny "<< BunnyColony[3].getName()<<" is " <<BunnyColony[3].getAge()<< " year's old."<<endl;
    cout<<"Bunny "<< BunnyColony[4].getName()<<" is " <<BunnyColony[4].getAge()<< " year's old."<<endl;

    cout<<"Done";
    return 0;
}
Last edited on
I've not looked in detail, but why?
1
2
3
4
5
6
7
8
    ~Bunny()                                                    //DESTRUCTOR
    {
        if(this->isVampire){cout<<"Radioactive mutant vampire bunny "<<this->getName()<<" died!"<<endl;}
        else{cout<<"Bunny "<<this->getName()<<" died!"<<endl;}
        POINTER=this;
        delete [] POINTER;
        POINTER=NULL;
    }
I too haven't looked at it in detail but line 153 isn't actually calling your order method. instead you are declaring a function prototype to the compiler.
ColonySort calls order.
order invokes delete on pointers.
Invoking delete on pointers causes the destructors of the pointed-to object to be called before freeing the memory associated with said object.

Why is a function called order deleting pointers?

As kbw points out, doing what is essentially delete [] this is wrong on more than one level in your code.
Last edited on
Like cire says, order() is the culprit.

these 2 lines are not required.
1
2
           delete[] PTR;
            PTR=NULL;


but you also have the following mismatch where PTR is a pointer to a single item and then try to delete an array of them.
1
2
Bunny *PTR;
delete[] PTR;


I see you are trying to delete the pointer, but delete actually deletes the object pointed to.
Don't cut and paste the same code at many places; factor it into a function.
Avoid hard-coded magic numbers 4, 5 etc.
Make getName() etc. const-correct.
Use the standard library: std::vector<>, std::sort<>
Do not keep copies of shared data (eg. F_names) with every object; make them static.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <algorithm>
#include <cstdio> // <stdio.h>
#include <cstring> // <string.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;

int GetRandom(int x){ return x>0 ? rand()%x : 0 ; }

class Bunny
{
private:
    static const vector<string> F_names ;
    static const vector<string> M_names ;
    static const vector<string> colors ;

    string name;
    string color = colors[ GetRandom( colors.size() ) ];
    int age = 0 ;
    bool isMale = GetRandom(2) == 0  ;
    string sex ;
    bool isVampire = GetRandom(10) < 2 ; // 20%
    string VampireString;

    void init()
    {
        sex = isMale ? "Male" : "Female" ;
        name = isMale ? M_names[ GetRandom( M_names.size() ) ] :
                        F_names[ GetRandom( F_names.size() ) ] ;
        VampireString = isVampire ? "Radioactive vampire mutant" : "normal" ;
        if( isVampire ) std::cout << "Radioactive mutant vampire " ;
        std::cout << "Bunny " << name << " (" << color << ") was born!\n" ;
    }

public:

    Bunny() { init() ; }
    Bunny( string clr ) { init() ; color = clr ; }

    ~Bunny()
    {
        if(isVampire) cout<<"Radioactive mutant vampire " ;
        cout << "Bunny " << name << " (" << color << ") died!\n" ;
    }

    bool getIsMale() const {return isMale;}
    string getName() const {return name;}
    string getSex() const {return sex;}
    string getColor() const {return color;}
    int getAge() const {return age;}
    bool isMature() const { return age >= 2 && isMale ; }

    void AddBabyToColony() {}
    void RemoveABunny() {}
    void PrintInfo() {}
};

const vector<string> Bunny::F_names = {"Hajra","Mejra","Sefika","Hanifa","Zulfa"};
const vector<string> Bunny::M_names = {"Wayne Rooney","Cristiano Ronaldo",
                                       "Edin Dzeko","Robin Van Persie","Juan Mata"};
const vector<string> Bunny::colors = {"white","brown","black","spotted"};

int main()
{
    int Total=5;
    srand(time(0));
    std::vector<Bunny> BunnyColony(Total);

    int Males=0;
    for( const Bunny& b : BunnyColony ) if( b.getIsMale() ) ++Males ;
    // int Females = BunnyColony.size() - Males ;

    std::cout.clear(std::ios::failbit) ; // silence cout
    std::sort( BunnyColony.begin(), BunnyColony.end(),
                []( const Bunny& a, const Bunny&b ) { return a.getAge() < b.getAge() ; } ) ;
    std::cout.clear() ; // unsilence cout

    for( const Bunny& b : BunnyColony )
        cout << "Bunny " << b.getName() << " is " << b.getAge() << " year's old.\n" ;

    cout << "Done\n" ;
}

http://coliru.stacked-crooked.com/a/5fac4fc96b707db0
Thanks you all for replying.
1.
I made
1
2
3
 POINTER=this;
        delete [] POINTER;
        POINTER=NULL;

this because I wanted to delete each bunny object when it dies (and to remove it from memory too). Is this the right way,or should I use some other way to free the memory up when a certain bunny dies?

2.
Why should I make get functions const-correct? It works even when they are regular,not constant.

I still didn't go throuh STL, and I don't know how to use templates and vectors. I'll try to learn it in next few days though..

@JLBorges:
This part of your code was impossible to understand, what did you actually do here:
1
2
3
4
std::cout.clear(std::ios::failbit) ; // silence cout
    std::sort( BunnyColony.begin(), BunnyColony.end(),
                []( const Bunny& a, const Bunny&b ) { return a.getAge() < b.getAge() ; } ) ;
    std::cout.clear() ; // unsilence cout 

Last edited on
> I wanted to delete each bunny object when it dies (and to remove it from memory too).
> Is this the right way

No, it is not the right way. The destructor of a Bunny object executes after the life of the bunny object is over, just before the memory is about to be reclaimed. Trying to delete the object that is currently being destroyed will result in an infinite recursion.


> Why should I make get functions const-correct?

See: http://www.gotw.ca/publications/advice98.htm
http://nova.polymtl.ca/~simark/Eff/Effective/0321334876/ch01lev1sec3.html
http://www.parashift.com/c++-faq-lite/const-correctness.html


> what did you actually do here:

We are going to sort Bunny objcts in ascending order of age. Sort reorders the sequence, it moves bunny objects around:
swap(a,b) : move a to temp, move b to a, move temp to b, destroy temp

We have a noisy destructor which prints out a message when an object is destroyed; std::cout.clear(std::ios::failbit) ; // silence cout puts cout into a failed state; it won't print these messages because its state is not good.

Once the sort is over, we want cout to start printing stuff again, so std::cout.clear() ; // unsilence cout puts cout back to a good state.

In between these,
1
2
std::sort( BunnyColony.begin(), BunnyColony.end(),
           []( const Bunny& a, const Bunny&b ) { return a.getAge() < b.getAge() ; } ) ;
actually sorts the Bunnys based on age.

See: http://www.cplusplus.com/articles/NhA0RXSz/
http://www.stroustrup.com/C++11FAQ.html#lambda
Last edited on
That was an awesome reply.
So if I understood you well, in this case, destructor of bunny class will delete a bunny object whenever it is called, even if there is a single cout expression and nothin else in destructor body?
So there is no need to use <code>delete </code> in destructor body?
Last edited on
The destructor is called by the code that deletes your object, the destructor does not delete the object it is destructing.
> destructor of bunny class will delete a bunny object whenever it is called,

It is the other way around. When the life-time of a bunny object is over, its destructor executes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>

struct Bunny
{
    Bunny( std::string name ) { id = name ; std::cout << id << " constructor\n" ; }
    ~Bunny() { std::cout << id << " destructor\n" ; }
    
    std::string id ;
};

int main()
{
    Bunny* bugs_bunny = new Bunny( "Bugs Bunny" ) ; 
    // step 1. aquire memory from the frfee store for a Bunny object
    // step 2. construct the bunny object
    
    {
        Bunny miyamoto( "Miyamoto Usagi" ) ; 
        // step 1. appropriate memory from the frame of the function (usually stack) for a Bunny object
        // step 2. construct the bunny object
        
        // miyamoto is alive now
        
    }// the life-time of miyamoto is over now.
    // step 1. destroy the bunny object
    // step 2. return memory occupied by the Bunny object back to the frame (stack)
    
    
    delete bugs_bunny ;
    // step 1. destroy the bunny object
    // step 2. release memory occupied by the Bunny object back to the free store
}

http://coliru.stacked-crooked.com/a/6a1ef4da44e2d154
Ok,I have one question left. What is this:
for( const Bunny& b : BunnyColony )
Isn't for loop supposed to look like this :
for(;;){*...*}?
Just as Java 5 introduced the "enhanced for-loop", C++11 added the "range-based for-loop". The expression to the right of the colon must support use of std::begin/std::end, and the variable to the left of the colon must be able to bind to (or copy from) the result of dereferencing the iterator.

These two code segments are roughly the same:
1
2
3
4
5
for(auto it = std::begin(SomeContainer); it != std::end(SomeContainer); ++it)
{
    Value const &v = *it;
    v.blah();
}
1
2
3
4
for(Value const &v : SomeContainer)
{
    v.blah();
}
Can you check out this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;


int GetRandom(int x){return rand()%x;}

class Bunny
{

private:
    static const vector <string> F_names;
    static const vector <string> M_names;
    static const vector <string> colors;
    bool isMale= GetRandom(2)<1 ? true : false;
    bool isVampire= GetRandom(100)< 2 ? true : false;
    string name;
    string color;
    string sex;
    string vampire;
    int age;
    void Inner(){
        age=0;
        sex= isMale ? "male" : "female";
        name= isMale ? M_names[GetRandom(10)] : F_names[GetRandom(5)];
        if(isVampire) cout<< "Radioactive mutant vampire ";
        cout<< "Bunny "<< name<< " was born."<<endl;
        vampire= isVampire? "yes":"no";
        }

public:

    Bunny()                                                     //DEFAULT CONSTRUCTOR
    { color=colors[GetRandom(4)]; Inner();}
    Bunny(string C)                                             //CHILDREN CONSTRUCTOR
    { color=C; Inner();}
    ~Bunny()                                                    //DESTRUCTOR
    {
        if(isVampire)cout<<"Radioactive mutant vampire ";
        cout<<"Bunny "<< name <<" died!"<<endl;
    }
    friend bool operator>  (  Bunny&,  Bunny&)  ;
    bool isMature() const {if(  (age>=2) &&(isMale) )return true; return false;}
    bool getIsMale() const {return isMale;}
    string getName() const {return name;}
    string getColor() const {return color;}
    string getSex()const {return sex;}
    string getVampire() const{return vampire;}
    bool getIsVampire() const {return isVampire;}
    int getAge() const {return age;}

    void RemoveABunny();
    void PrintInfo();
    void increaseAge();
};

    const vector <string> Bunny::F_names={"Hajra","Mejra","Sefika","Hanifa","Zulfa"};
    const vector <string> Bunny::M_names={"Wayne Rooney","Cristiano Ronaldo","Edin Dzeko",
    "Robin Van Persie","Juan Mata","David De Gea","Luis Nani","Ryan Giggs","Paul Scholes","David Beckham"};
    const vector <string> Bunny::colors={"white","brown","black","spotted"};

     bool operator> (  Bunny& a,  Bunny& b) {return (a.age)>(b.age);}


    const void AddBabyToColony(const string &Clr, vector<Bunny> & Colony)
    {
        Colony.push_back(Bunny(Clr));
    }

    const void PrintColony(const vector<Bunny> & Colony ,int x=0 )
    {
        cout<<"\n\nColony information in turn number: "<< x<<endl;
        cout<<"AGE\t\tSEX\t\tCOLOR\t\tVAMPIRE STATUS\t\tNAME\n";
        for(int i=0; i<Colony.size() ; i++)
        {
            cout<<Colony[i].getAge()<<"\t\t"<<Colony[i].getSex()<<"\t\t"<<Colony[i].getColor();
            cout<<"\t\t"<<Colony[i].getVampire()<<"\t\t"<<Colony[i].getName()<<"\n"<<endl;
        }
        cout<<"\n\n\n";
    }

int main()
{
    int Males=0;
    int Females=0;
    int Total=5;
    srand(time(0));
    vector <Bunny> BunnyColony(Total);
    for( int i=0 ; i< 5; i++) if(BunnyColony[i].getIsMale()) Males++;

    PrintColony(BunnyColony);                    //HERE EVERYTHING IS OK

    AddBabyToColony("Red",BunnyColony);    //BUT THE THE PROBLEM IS HERE

    

    cout<<"Done\n";
    return 0;
}

When I call [code]AddBabyToColony("Red",BunnyColony);
it creates one new bunny,and after that ,that all bunnies die. I don't want them to die, what did I do wrong this time?
Well the program ends why do you not want them to die? Bunnies do not belong in the stack when the program completes.
No no,bunnies die before line 103,so actualy die once after line 99, and than cout<<"Done\n"; is executed and again they somehow die. I hope you udnerstand me.

They die twice, after line 99 and on the end of program.
Last edited on
> AddBabyToColony("Red",BunnyColony); //BUT THE THE PROBLEM IS HERE

The memory for the vector is reallocated when you add a new bunny.
a. Allocate a larger buffer
b. Create bunnies in the new buffer which are copies of the bunnies in the old buffer.
c. Add bunny "Red" at the end of the new buffer
c. Destroy bunnies in the old buffer (this is what you are seeing)
d. Release memory for the old buffer.


> friend bool operator> ( Bunny&, Bunny&) ;

Make this const-correct

> const void AddBabyToColony(const string &Clr, vector<Bunny> & Colony)

remove spurious const on return type.


> Colony.push_back(Bunny(Clr));

This will create a temporary bunny object, copy it into the vector, and then destroy the anonymous temporary bunny. This can be avoided by constructing the bunny directly in the vector with emplace_back()

Modify as follows and observe the behaviour (no reallocation is required because we have reserved adequate space before hand; no anonymous temporary bunny is created because we have used emplace).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;


int GetRandom(int x){return rand()%x;}

class Bunny
{

private:
    static const vector <string> F_names;
    static const vector <string> M_names;
    static const vector <string> colors;
    bool isMale= GetRandom(2)<1 ? true : false;
    bool isVampire= GetRandom(100)< 2 ? true : false;
    string name;
    string color;
    string sex;
    string vampire;
    int age;
    void Inner(){
        age=0;
        sex= isMale ? "male" : "female";
        name= isMale ? M_names[GetRandom(10)] : F_names[GetRandom(5)];
        if(isVampire) cout<< "Radioactive mutant vampire ";
        cout<< "Bunny "<< name<< " was born."<<endl;
        vampire= isVampire? "yes":"no";
        }

public:

    Bunny()                                                     //DEFAULT CONSTRUCTOR
    { color=colors[GetRandom(4)]; Inner();}
    Bunny(string C)                                             //CHILDREN CONSTRUCTOR
    { color=C; Inner();}
    ~Bunny()                                                    //DESTRUCTOR
    {
        if(isVampire)cout<<"Radioactive mutant vampire ";
        cout<<"Bunny "<< name <<" died!"<<endl;
    }
    friend bool operator>  (  const Bunny&,  const Bunny&)  ; // **** made const correct
    bool isMature() const {if(  (age>=2) &&(isMale) )return true; return false;}
    bool getIsMale() const {return isMale;}
    string getName() const {return name;}
    string getColor() const {return color;}
    string getSex()const {return sex;}
    string getVampire() const{return vampire;}
    bool getIsVampire() const {return isVampire;}
    int getAge() const {return age;}

    void RemoveABunny();
    void PrintInfo();
    void increaseAge();
};

    const vector <string> Bunny::F_names={"Hajra","Mejra","Sefika","Hanifa","Zulfa"};
    const vector <string> Bunny::M_names={"Wayne Rooney","Cristiano Ronaldo","Edin Dzeko",
    "Robin Van Persie","Juan Mata","David De Gea","Luis Nani","Ryan Giggs","Paul Scholes","David Beckham"};
    const vector <string> Bunny::colors={"white","brown","black","spotted"};

     bool operator> ( const Bunny& a,  const Bunny& b) {return (a.age)>(b.age);}


    /*const*/ void AddBabyToColony(const string &Clr, vector<Bunny> & Colony) // removed const on return type  
    {
        Colony.emplace_back(Clr); // **** use emplace_back instead of push_back
                                  // avoid the creation and destruction of a temporary bunny object     
    }

    void PrintColony(const vector<Bunny> & Colony ,int x=0 ) // removed const on return type
    {
        cout<<"\n\nColony information in turn number: "<< x<<endl;
        cout<<"AGE\t\tSEX\t\tCOLOR\t\tVAMPIRE STATUS\t\tNAME\n";
        for( std::size_t i=0; i<Colony.size() ; i++)
        {
            cout<<Colony[i].getAge()<<"\t\t"<<Colony[i].getSex()<<"\t\t"<<Colony[i].getColor();
            cout<<"\t\t"<<Colony[i].getVampire()<<"\t\t"<<Colony[i].getName()<<"\n"<<endl;
        }
        cout<<"\n\n\n";
    }

int main()
{
    int Males=0;
    //int Females=0;
    int Total=5;
    srand(time(0));
    
    //vector <Bunny> BunnyColony(Total);
    
    vector <Bunny> BunnyColony ; // create an empy vector
    BunnyColony.reserve(1000) ; // reserve space dor 1000 bunnies
    BunnyColony.resize(Total) ; // put in the initial 'Total' bunnies
    
    for( int i=0 ; i< 5; i++) if(BunnyColony[i].getIsMale()) Males++;

    PrintColony(BunnyColony);                    //HERE EVERYTHING IS OK

    AddBabyToColony("Red",BunnyColony);    //BUT THE THE PROBLEM IS HERE

    

    cout<<"Done\n";
    return 0;
}

http://coliru.stacked-crooked.com/a/a616bfe62f712163
JLBorges,thank you once again. I appreciate your help.
EDIT 2: I fixed it. I forgot to silence "cout" statement while sorting the vector. It's fixed now. Sorry for inconvenience.

(Other part of the code is same as in JLBorges' last post.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
int main()
{
    int Males=0;
    int Females=0;
    int Total=5;
    srand(time(0));
    vector <Bunny> BunnyColony;
    BunnyColony.reserve(2000);
    BunnyColony.resize(Total);
    for( int i=0 ; i< 5; i++) if(BunnyColony[i].getIsMale()) Males++;

    PrintColony(BunnyColony);
    int cont;

   for(int turn=1; ;turn++)                   //PROBLEM HAPPENS SOMEWHERE FROM THIS LINE
    {
        for(int i=0;i<Total;i++) BunnyColony[i].increaseAge();
        for(int i=0; i<Total; i++)
        {
            if(BunnyColony[i].isMatureMale())
            {
                for(int j=0;j<Total;j++)
                {
                    if(BunnyColony[j].isMatureFemale())
                    {
                        AddBabyToColony(BunnyColony[j].getColor(),BunnyColony,Total);
                    }
                }
            }
            if(BunnyColony[i].isMatureMale()) break;
        }                         

        Sort(BunnyColony);
        PrintColony(BunnyColony,turn);

         if(turn%4==0) {cout<<"total is "<<Total<< ", pause: "<<endl; cin>>cont;}
    }                                   //TO THIS LINE


    cout<<"Done\n";
    return 0;
}

It somehow happens that these for and if sentences also make copies of objects,and delete them on each iteration,which also produces destructor Cout message.
What could be the reason for that?

EDIT:
My bad, I did add some new lines,here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
bool operator> ( const Bunny& a, const Bunny& b) {return (a.age)>(b.age);}
    bool operator< ( const Bunny& a, const Bunny& b) {return (a.age)<(b.age);}

    void Bunny::increaseAge(){ this->age++;}

    void AddBabyToColony(const string &Clr, vector<Bunny> & Colony,int & total) // removed const on return type
    {
        Colony.emplace_back(Clr); 
         total++;                         
    }



    void Sort(vector<Bunny> &Colony)
    {
        sort(Colony.rbegin(),Colony.rend());
    }

    void PrintColony(const vector<Bunny> & Colony ,int x=0 ) 
    {
        cout<<"\n\nColony information in turn number: "<< x<<endl;
        cout<<"AGE\t\tSEX\t\tCOLOR\t\tVAMPIRE STATUS\t\tNAME\n";
        for( std::size_t i=0; i<Colony.size() ; i++)
        {
            cout<<Colony[i].getAge()<<"\t\t"<<Colony[i].getSex()<<"\t\t"<<Colony[i].getColor();
            cout<<"\t\t"<<Colony[i].getVampire()<<"\t\t"<<Colony[i].getName()<<"\n"<<endl;
        }
        cout<<"\n\n\n";
    }


Most probably the problem is somewhere here:
1
2
3
4
void Sort(vector<Bunny> &Colony)
    {
        sort(Colony.rbegin(),Colony.rend());
    }

This part somehow creates copy objects and destroy them in the end,which produces the destructor messages. How to turn that off?
Last edited on
> I fixed it. I forgot to silence "cout" statement while sorting the vector.

Try this (silence bunnys who have moved to another address):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <string>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <ctime>

struct bunny
{
    bunny() { std::cout << *this << " was born\n" ; }

    bunny( std::string name, int age, std::string clr )
        : name(name), age(age), colour(clr)
    { std::cout << *this << " was born\n" ; }

    ~bunny() noexcept { if( !has_moved_elsewhere ) std::cout << *this << " died\n" ; }

    // bunnies can't be copied
    bunny( const bunny& ) = delete ;
    bunny& operator= ( const bunny& ) = delete ;

    // but thay can be moved
    bunny( bunny&& that ) noexcept
         : name( std::move(that.name) ), age(that.age),
           colour(that.colour), has_moved_elsewhere(that.has_moved_elsewhere)
           { that.has_moved_elsewhere = true ; }

    bunny& operator= ( bunny&& that ) noexcept
    {
        std::swap( name, that.name ) ;
        age = that.age ;
        colour = that.colour ;
        has_moved_elsewhere = that.has_moved_elsewhere ;
        that.has_moved_elsewhere = true ;
        return *this ;
    }

    private:
        static const std::vector<std::string> names ;
        static const std::vector<std::string> colours ;

        std::string name = names[ std::rand() % names.size() ] ;
        int age = std::rand() % 10 ;
        std::string colour = colours[ std::rand() % colours.size() ] ;
        bool has_moved_elsewhere = false ;

    friend std::ostream& operator<< ( std::ostream& stm, const bunny& b )
    { return stm << "bunny{ " << b.name << ", " << b.age << ", " << b.colour << " }" ; }

    friend bool operator< ( const bunny& a, const bunny& b ) { return a.age < b.age ; }
};

const std::vector<std::string> bunny::names =
{
    "Hajra", "Mejra", "Sefika", "Hanifa", "Zulfa", "Wayne Rooney",
    "Cristiano Ronaldo", "Edin Dzeko",  "Robin Van Persie", "Juan Mata",
    "David De Gea", "Luis Nani", "Ryan Giggs", "Paul Scholes", "David Beckham"
};

const std::vector<std::string> bunny::colours =
{
    "white", "brown", "black", "spotted", "agouti", "blue", "cinnamon",
    "lynx", "chinchilla", "sable", "smoke pearl", "fawn", "tan"
};

int main()
{
    std::srand( std::time(nullptr) ) ;

    std::vector<bunny> colony ;

    colony.push_back( bunny( "bugs", 5, "white" ) ) ;
    colony.push_back( bunny( "miyamoto", 7, "dove-grey" ) ) ;
    colony.push_back( bunny( "bre'r", 4, "beige" ) ) ;
    colony.resize(8) ;

    std::sort( std::begin(colony), std::end(colony) ) ;

    std::cout << "---------------------------------------------\n" ;
    for( const bunny& b : colony ) std::cout << b << " is alive\n" ;

    std::cout << "---------------------------------------------\n" ;
}

http://coliru.stacked-crooked.com/a/8b20547d6522b85e
Pages: 12