c++ - 从存储在 vector 中的指针获取对象属性

标签 c++ oop pointers vector dynamic-memory-allocation

简洁描述

我无法找出问题所在,由于某种不明原因,我将指针存储在 vector 中的对象的属性似乎已更改。

详细说明

我有一个兔子类,看起来像这样:

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 );
}

现在它是一个非常基本的类,析构函数仍然是空的,并且它有一些属性。 我还有一个类型为 vector<Rabbit*> 的指针 vector

vector<Rabbit*> rabbits = vector<Rabbit*>(0);

我用它来存储指向新创建的兔子的指针。 我将新创建的兔子的指针传递给该 vector ,如下所示。

Rabbit* adam ;
adam = new Rabbit();
adam->setSexe(Rabbit::MALE);
rabbits.push_back(adam);
delete adam ; //I think we don't 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

但是当我尝试访问指针已存储在 vector 中的兔子的性别属性时,我遇到了麻烦。

Rabbit* rabbit_p = rabbits.at(r) ;
cout << rabbit_p->sex << endl ; // prints a verry high number instead of 1 or 2

所以我的问题是为什么会发生这种情况,我是否在不知不觉中引用了堆中的另一个位置并读出了另一个值?为什么?

下面我将包含整个源代码,它与正确的兔子面包屑行为相去甚远,但我想测试对象的动态内存分配。起初 vector 只包含普通的兔子,但内存没有释放,所以现在我正在测试指针方法。

完整来源

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);
    }
    
}

最佳答案

这里

Rabbit* adam ;
adam = new Rabbit();
adam->setSexe(Rabbit::MALE);
rabbits.push_back(adam);
delete adam ;

vector 内有一个悬空指针。 vector 仅深层复制用作 vector 参数的类型的对象 - 在您的情况下,它是 Rabbit*,而不是 Rabbit 。因此只复制指针,而不复制对象。

稍后您检索并使用该悬空指针并调用未定义的行为。

关于c++ - 从存储在 vector 中的指针获取对象属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6611033/

相关文章:

c++ - 使用 clang v3.4 在 ubuntu_x86-64 上为 arm 编译一个 c/c++ 源文件

c++ - 如何从 lldb 执行函数(由指针标识)

c++ - QThreads之间如何发送数据?

javascript - 如何在构造函数中创建一个 JS 对象并将 "parent object"作为构造函数参数?

c - 声明一个指向内存中地址 0x200 处的整数的指针

C++ - 成员对象中枚举的行为

c++ - 是什么阻止用户空间程序切换到更高级别?

不能从 class.__dict__ 调用 python 类方法

c - 为什么连续数组条目的地址不是连续的?

oop - 在 TypeScript 中访问外部类的成员