Are the objects in both vectors the same instance of the object? Like if I called vectorOne[0].setValue(somethingDifferent); would the value be changed for the object in both vectorOne and vectorTwo? If not, how do I make sure that I only have one instance of the object I'm trying to store in multiple vectors?
Are the objects in both vectors the same instance of the object?
No. vector::push_back(obj) stores a copy of obj in the vector. If you want to have the same instance in both vectors then you'll need to use a vector of pointers:
Any time you create a collection of pointers you need to be crystal clear about who owns the objects that are pointed to? This boils down to "who is responsible for deleting them?" Don't do this as an afterthought - it needs to be defined first and then all code needs to obey the rule.
Alright, got it. So if I used a function to add the object to the vectors, how would that look? Here's what I have that doesn't throw any errors:
1 2 3 4 5 6 7 8
class Class{
//...
void AddObject(Object object){ vectorOne.push_back(&object); }
std::vector<Object*> vectorOne;
};
//then when calling it
AddObject(object);
//and do the same thing for the other vectors
Does this make sure that there is only one instance of the object even in multiple vectors?
Not as you've implemented it. You are passing object by value to the add object function. A local copy of object is created for use in the function. You are storing a pointer to a local copy (out of scope when function exits), not a pointer to object in main(). This can cause big problems.
Pass object by reference instead.
Here's some sample code to demonstrate the problem with pass by value here.
I defined a copy ctor for the Object class so we can see that a temp instance is created when the void showCopyOfObject_Address( Object obj ) function is called.
As I said in my first post, you need to decide who owns the objects that the vector points to. The problem that funcode2 points out demonstrates why this is so important.
@dhayden a class called Board holds the instances, and whenever the current Board object is destroyed and a new one is loaded can I then delete all the pointers in Board's destructor?
And so basically, the change I need to make in my implentation is passing by reference in the function paramters? Like so void AddObject(Object &object){ vectorOne.push_back(&object); }
Edit: This seems to work, because across all vectors the object's value is changed when I change it for one vector. However, when actually trying to draw these objects, the screen seems to be glitching out. I have the code set up like this:
1 2 3 4 5 6 7 8
//loop through all vectors of objects
if(object.drawn == false){
window.draw(object);
object.drawn = true;
}
//then after the gameloop is done
object.drawn = false;
I have it set up like this because multiple vectors have the oppurtunity to own a pointer to object, so the object is possibly being drawn multiple times as those vectors loop through themselves. This may be an SFML question at this point, but I still feel like I'm doing something wrong on the c++ side of things.
So like once every 100 loops or so, the window actually displays the objects, otherwise it stays empty.
Any time you create a collection of pointers you need to be crystal clear about who owns the objects that are pointed to? This boils down to "who is responsible for deleting them?" Don't do this as an afterthought - it needs to be defined first and then all code needs to obey the rule.
This.
When you have a dynamically allocated object, you must keep track of it and ensure appropriate deletion.
When you have more than one "pointers" to such object and one is the owner, how do you ensure that non-owners are removed before the deletion? The std::shared_ptr is one answer: they are all owners and the last to go does the delete.
So would my class that holds the objects still have a vector of regular objects? I.e. std::vector<Object> vectorOne; And then in other classes that have vectors of pointers to those objects I would do this? std::vector<std::shared_ptr<Object>> vectorPointerOne; Or would all vectors, even the one which holds the actual instances, be vectors of shared pointers?
No. As has been said already, when you pass an object into a vector, that creates copies of those objects that are managed by the vector. Any pointers you have to the objects in the vector would be unreliable, because the vector can manage its own memory, allocating and deleting new memory as it chooses.
If you want pointers to objects, you'll have to have some part of your program take ownership of those objects.
I'm not sure if I did this correctly or if I just need a new way of handling these objects, but when I try to draw objects from the movableObjects_; vector using window.draw(board.GetGrid()[i].GetGridObjects()[j]->GetActiveSprite()); //this line of code worked when I was just using regular pointers, and quit drawing anything when I switched to shared_ptr's nothing is drawn on the screen. This same code worked when my class just held vectors of regular pointers, but when I implemented shared pointers the screen quit drawing anything.
The code you've posted for your movableObjects_, AddMovableObject() and GetMovableObjects() looks OK to me. I'd recommend defining a typedef for std::vector<std::shared_ptr<MoveableObject>> to make your code a bit easier to read, but that's a matter of style.
Without knowing anything about that draw method, we have no way of knowing why it might not be drawing.
At this point, the most productive thing you can do is run the code through a debugger so that you can examine the state of the memory at various points at which you're using that array.
class MyDrawable : public sf::Drawable
{
public:
...
private:
virtualvoid draw(sf::RenderTarget& target, sf::RenderStates states) const
{
// You can draw other high-level objects
target.draw(m_sprite, states);
// ... or use the low-level API
states.texture = &m_texture;
target.draw(m_vertices, states);
// ... or draw with OpenGL directly
glBegin(GL_QUADS);
...
glEnd();
}
sf::Sprite m_sprite;
sf::Texture m_texture;
sf::VertexArray m_vertices;
};
So each object calls this draw method implicitly, as it is a pure virtual function. So in the code, m_sprite is the same thing as the object that my smart pointer is pointing to, because each object owns a sf::sprite object.