Компактное описание
У меня проблема с выяснением, что не так, по какой-то непонятной причине свойства объекта, для которого я сохранил указатель в векторе, похоже, изменились.
Подробное объяснение
У меня есть класс Кролик, который выглядит следующим образом.
class Rabbit {
enum sexes { MALE = 0x1, FEMALE = 0x2 } ;
int sex ;
bool has_mated ;
Rabbit();
~Rabbit();
void setSexe(int sex);
void match( vector<Rabbit*> &rabbits );
void breed( Rabbit &partner, vector<Rabbit*> &rabbits );
}
Пока это базовый класс Verry, деструктор все еще пуст и имеет несколько свойств.
У меня также есть указатель-указатель типа vector
vector<Rabbit*> rabbits = vector<Rabbit*>(0);
который я использую для хранения указателей на только что созданных кроликов.
Я даю указатели вновь созданным кроликам на этот вектор вот так.
Rabbit* adam ;
adam = new Rabbit();
adam->setSexe(Rabbit::MALE);
rabbits.push_back(adam);
delete adam ; //i think we dont need the pointer anymore as we copied it to the vector
Мое намерение - освободить память всякий раз, когда кролика отрывают вот так.
(Я надеюсь, что это правильный путь)
Rabbit* dead_rabbit = rabbits.back(); //obtain the pointer
delete dead_rabbit ; //free the associated memory
rabbits.pop_back(); //delete the pointer itself
Но у меня возникают проблемы, когда я пытаюсь получить доступ к свойству пола кролика, для которого указатель хранится в векторе
Rabbit* rabbit_p = rabbits.at(r) ;
cout << rabbit_p->sex << endl ; // prints a verry high number instead of 1 or 2
Итак, мой вопрос: почему это происходит, я неосознанно обращаюсь к другому месту в куче и зачитываю другое значение? а почему?
Ниже я приведу весь исходный код, он далек от правильного поведения кролика;) но я хотел проверить динамическое назначение памяти для объектов. Сначала вектор содержал только простых кроликов, но память не была освобождена, поэтому сейчас я тестирую подход с указателем.
Полный источник
using namespace std ;
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <iterator>
#include <sys/time.h>
#include <sys/resource.h>
class Rabbit {
public:
enum sexes { MALE = 0x1, FEMALE = 0x2 } ;
int sex ;
bool has_mated ;
Rabbit();
~Rabbit();
void setSexe(int sex);
void match( vector<Rabbit*> &rabbits );
void breed( Rabbit &partner, vector<Rabbit*> &rabbits );
};
Rabbit::Rabbit(){
this->sex = random() % 2 + 1 ; //random m/f
this->has_mated = false ;
}
Rabbit::~Rabbit(){
}
void Rabbit::setSexe( int sex ){
this->sex = sex ;
}
void Rabbit::match(vector<Rabbit*> &rabbits){
int s = rabbits.size() ;
int r = 0 ;
for(r ; r < s ; r++ ){
Rabbit* partner_ptr = rabbits.at(r) ;
Rabbit partner = *partner_ptr ;
if( partner.sex == Rabbit::MALE && partner.has_mated == false ){
this->breed(partner, rabbits);
this->has_mated = true ;
partner.has_mated = true ;
break ;
}
}
}
void Rabbit::breed( Rabbit &partner, vector<Rabbit*> &rabbits ){
int offspring, sex ;
offspring = random() % 4 + 3 ;
cout << "breeding " << offspring << " rabbits..." << endl ;
Rabbit* temp_rabbit ;
for(int i=0; i < offspring; i++){
int sex = random() % 2 + 1 ;
temp_rabbit = new Rabbit() ;
temp_rabbit->setSexe(sex);
rabbits.push_back(temp_rabbit);
cout << "one rabbit has been born." << endl ;
}
}
//makes rabbits date each other
void match_rabbits(vector<Rabbit*> & rabbits){
cout << "matching rabbits..." << endl ;
for(int r = 0; r < rabbits.size() ; r++ ){
Rabbit* first_rabbit_p = rabbits.front();
Rabbit* nth_rabbit_p = rabbits.at(r);
cout << "pointer to first rabbit: "<< first_rabbit_p << endl ;
cout << "pointer to rabbit n° " << r << ": " << nth_rabbit_p << "( " << sizeof( *nth_rabbit_p ) << "B )" << endl ;
cout << "sex parameter of dereferenced rabbit: " << rabbit.sex << endl ;
/*
if( rabbit.sex == Rabbit::FEMALE && rabbit.has_mated == false){
cout << "found a female" << endl ;
rabbit.match(rabbits) ;
} */
}
}
void pop_rabbits(vector<Rabbit*> & rabbits, int n){
vector<Rabbit*>::iterator rabbits_iterator ;
for(int r = 0 ; r < rabbits.size() ; r++ ){
Rabbit* rabbit = rabbits.back();
delete rabbit ;
rabbits.pop_back();
}
}
int main( int argc , const char* argv[] ){
srand(time(NULL));
vector<Rabbit*> rabbits = vector<Rabbit*>(0) ;
Rabbit* adam ;
adam = new Rabbit();
adam->setSexe(Rabbit::MALE) ;
Rabbit* eve ;
eve = new Rabbit() ;
eve->setSexe(Rabbit::FEMALE) ;
char * input;
input = new char[2] ;
try{
//populate with 2 rabbits.
rabbits.push_back(adam);
rabbits.push_back(eve);
delete adam ;
delete eve ;
do {
//memory_usage = getrusage(RUSAGE_SELF, struct rusage *usage);
if(rabbits.size() < 2){
break ;
}
cout << rabbits.size() << " rabbits ( " << "K )" << endl ;
cout << "Shoot some rabbits ? (Y/N) :" << endl ;
delete[] input ;
input = new char[2] ;
cin.getline(input,2);
if( strcmp(input,"Y") == 0 || strcmp(input,"y") == 0){
cout << "How many ? :" << endl ;
delete[] input ;
input = new char[16] ;
cin.getline(input,16);
pop_rabbits(rabbits, atoi(input));
continue ;
}
cout << "Continue ? (Y/Q) :" << endl ;
delete[] input ;
input = new char[2] ;
cin.getline(input,2);
if(strcmp(input,"Y") == 0 || strcmp(input,"y") == 0){
match_rabbits(rabbits);//let the rabbits date
}
if(strcmp(input,"Q") == 0 || strcmp(input,"q") == 0){
break ;
}
} while( true );
exit(0);
} catch ( exception& e ){
cout << e.what() << endl ; //print error
exit(1);
}
}