Pass a std :: vector by reference (Avoid Copy)

3

I am developing a mini-game. The classes involved in this question are:

  • PlayState
  • IA
  • Terrorist.

PlayState gives a Terrorist Vector to IA .

Intelligence = new IA(terrorists, p->getRigidBody(), _world);

The definition of the Vector and the terrorist

Terrorist *unTerrorista; 
std::vector<Terrorist*> terrorists;

So, I'm creating a vector that contains a pointer to terrorists and I give it to IA . What I want is that IA delete terrorists and update automatically in PlayState (to avoid working with 2 vectors)

Extra information:

IA.h

class IA { 
public: 
IA(std::vector<Terrorist*> &pTerrorists, RigidBody *pPlayer, OgreBulletDynamics::DynamicsWorld *pWorld); 
IA(const IA& orig); 
virtual ~IA(); 
void updateWorld(Ogre::Real pDeltaT); 
private: 

// int patrullando, rastreando, atacando, muerto; 
bool notifyAllTerrorists; 
Ogre::Real deltaT; 
Ogre::Real auxT; 
RigidBody *player; 
std::vector<Terrorist*> &terrorists; 
OgreBulletDynamics::DynamicsWorld *world; 
};

IA.cpp

IA::IA(std::vector<Terrorist*> &pTerrorists, RigidBody *pPlayer, OgreBulletDynamics::DynamicsWorld *pWorld) {
    terrorists = pTerrorists;
    player = pPlayer;
    world = pWorld;
}
    
asked by Strelok 04.07.2017 в 10:52
source

2 answers

3

The IA can, instead of receiving a copy of the vector, receive a reference to PlayState :

class IA
{
  PlayState& ps;

public:

  IA(PlayState& ps, /* ... */ )
    : ps{ps}
  {
  }

  void BorrarTerrorista()
  {
    if( !ps.terrorists.empty() )
    {
      delete ps.terrorists.back();
      ps.terrorists.pop_back();
    }
  }
};

It can also happen that you do not want terrorists to be a public access vector. In which case you need a function that allows you to eliminate the desired element. This solution allows launching events every time falls a terrorist

class PlayState
{
  std::vector<Terrorist*> terrorists;

public:

  void NuevoTerrorista(Terrorist* t)
  {
    terrorists.push_back(t);

    // Avisamos de que hay un terrorista
  }

  void BorrarTerrorista(Terrorist* t)
  {
    auto it = std::find(terrorists.begin(),terrorists.end(),t);
    if( it != terrorists.end() )
    {
      delete *it;
      terrorists.erase(it);

      // Avisamos de que hay un terrorista menos
    }
  }
};

class IA
{
  PlayState& ps;

public:

  IA(PlayState& ps, /* ... */ )
    : ps{ps}
  {
  }

  void BorrarTerrorista()
  {
    // Algoritmo para elegir el terrorista a eliminar
    Terrorist* t = /* ... */

    ps.BorrarTerrorista(t);
  }
};

Of course you can always pass a reference to the vector ... but then the notifications for the rest of the components to work correctly are carried out by IA :

class IA
{
  std::vector<Terrorists*>& terrorists;
  //                      ^ Importante!!!!!

public:
  IA(std::vector<Terrorists*>& terrorists, /* ... */ )
    : terrorists{terrorists}
  { }

  void BorrarTerrorista()
  {
    // Algoritmo para elegir el terrorista a eliminar
    Terrorist* t = /* ... */

    auto it = std::find(terrorists.begin(),terrorists.end(),t);
    if( it != terrorists.end() )
    {
      delete *it;
      terrorists.erase(it);
      // Lanzar avisos
    }
  }  
};
IA::IA(std::vector<Terrorist*> &pTerrorists, RigidBody *pPlayer, OgreBulletDynamics::DynamicsWorld *pWorld) {
    terrorists = pTerrorists;
//  ^^^^^^^^^^

What is terrorists ? Should not it be pTerrorists ? Notice that in my response I told you to do this:

IA::IA(std::vector<Terrorist*> &pTerrorists, RigidBody *pPlayer, OgreBulletDynamics::DynamicsWorld *pWorld)
  : pterrorists(pTerrorists)
{ }

Whose alternative it would be:

IA::IA(std::vector<Terrorist*> &pTerrorists, RigidBody *pPlayer, OgreBulletDynamics::DynamicsWorld *pWorld) {
    this->pTerrorists = pTerrorists;
    
answered by 04.07.2017 в 11:05
1

I do not see what your problem is, correct me if I'm wrong.

Define an alias for terrorist vector:

using terrorist_vector = std::vector<Terrorist*>;

And use reference (modifiable) in your object IA :

// Referencia ----> v
IA(terrorist_vector &pT, RigidBody *pP, OgreBulletDynamics::DynamicsWorld *pW)
{
    ...
    ...
}

Since you are saving the vector as a reference within the class IA , you will need to use the initialization list of the constructor to give it value:

// Referencia ----> v
IA(terrorist_vector &pT, RigidBody *pP, OgreBulletDynamics::DynamicsWorld *pW) :
    terrorists(pT) // <---- inicializa aquí.
{
    ...
    ...
}

You can have more information about why it is necessary to do it that way in this answer .

    
answered by 04.07.2017 в 11:05