Pointer to a vector doesn't point - c++

I have simplified the code as much as possible.
So I have two class:
class EntityManager
{
public:
std::shared_ptr<std::vector<Entity> > getEntities()
{
return std::make_shared<std::vector<Entity> >(m_entities);
}
private:
std::vector<Entity> m_entities{};
};
and
class System
{
public:
void loadEntities(std::shared_ptr<std::vector<Entity> > entities)
{
m_entities = entities;
}
private:
std::shared_ptr<std::vector<Entity> > m_entities;
};
Now basically I want the m_entities of System to point to the m_entities of EntityManager.
I did this:
system = System();
system.loadEntities(m_entityManager.getEntities());
But then I pushed back an element into the m_entities vector of EntityManager and this element wasn't added in the m_entities vector of System, which means my pointer doesn't point.
Where is my mistake?
Thanks!

Your problem is this line: return std::make_shared<std::vector<Entity> >(m_entities);
What is happening is that the shared_ptr manages a new std::vectory<Entity> container which is initialized as a copy of m_entities. Therefore, modifying the instance in the shared_ptr doesn't modify the data member in the EntityManager class and of course the shared_ptr won't see changes made to EntityManager::m_entities.

std::make_shared doesn't "make this thing shared"; it "makes a thing that will be shared".
So, you can't just make a shared pointer out of nowhere that points to something that already exists.
Your code dynamically allocates a std::vector, copy constructed from m_entities and managed by a std::shared_ptr. It's shorthand for this:
std::vector<Entity>* ptr_to_copy = new std::vector<Entity>(m_entities);
return std::shared_ptr(ptr_to_copy);
It's not clear what you're trying to do, from the code that (by your own admission) does not achieve that goal. But it seems unlikely that std::shared_ptr is appropriate here.
If it is, then make the vector dynamically-allocated and shared from the start; otherwise, just return a reference to the vector as it is.

Hack example of a pointer-free solution.
#include <string>
#include <iostream>
#include <vector>
//Hack-sample Entity class
class Entity
{
public:
Entity(const char * name): m_name(name)
{
}
void print() // this is stupid in real life. Prefer a << overload
{
std::cout << "Hi! I'm " << m_name << "!\n";
}
private:
std::string m_name;
};
class EntityManager
{
private:
std::vector<Entity> m_entities;
public:
// hide the fact that a vector is being used to store the entities.
// you can now swap out the vector for most standard containers without
// changing any code other than the using and the declaration of m_entities
using iterator = std::vector<Entity>::iterator;
EntityManager(): m_entities({"bob", "bill"})
// just pre-loading a few test entities
{
// RAII says you should load the entities from their source here
}
// get the first entity.
iterator begin()
{
return m_entities.begin();
}
// get the end of the entity list
iterator end()
{
return m_entities.end();
}
// adds an entity
void addEntity(const Entity & entity)
{
m_entities.push_back(entity);
}
// removes an entity
iterator removeEntity(iterator rem)
{
return m_entities.erase(rem);
}
};
class System
{
public:
// example method to show System working with EntityManager by printing all of the Entities
void printEntities()
{
for (EntityManager::iterator it = m_entityManager.begin();
it != m_entityManager.end();
++it)
{
it->print();
}
}
// example method to show System working with EntityManager by adding Entities
void addMoreEntities()
{
m_entityManager.addEntity(Entity("Ted \"Theodore\" Logan"));
m_entityManager.addEntity(Entity("Excellent!!!"));
}
private:
EntityManager m_entityManager ;
};
// sample test
int main()
{
System test;
test.printEntities();
test.addMoreEntities();
test.printEntities();
}
THIS HAS BEEN A HACK. THIS HAS ONLY BEEN A HACK.
If you want to do EntityManager right, see Writing your own STL Container for hints. If you want all of the bells and whistles, the job is fairly complicated. Depending on how you are using EntityManager and the complexity of the Entity management logic, you may be better off discarding EntityManager and just using the plain, old std::vector.
Addendum: What is meant by Resource Acquisition is Initialization (RAII)?

Related

How can i add(or append)class object to different class object array

I have this Book class objects (base class: Product)
Book books[5] = {
Book("Kucuk Prens","FR","Roman","Book",10,15,103061,12,"Kultur yayinlari",10),
Book("Kucuk Prens1","FR","Roman","Book",10,15,103061,12,"Kultur yayinlari",10),
Book("Kucuk Prens2","FR","Roman","Book",10,15,103061,12,"Kultur yayinlari",10),
Book("Kucuk Prens3","FR","Roman","Book",10,15,103061,12,"Kultur yayinlari",10),
Book("Kucuk Prens4","FR","Roman","Book",10,15,103061,12,"Kultur yayinlari",10)};
And I have a Cart class.
class Cart
{
private:
int totalPrice;
Product productList[5]; // kullanıcın seçtiği
public:
};
For instance, I want to add books[1] to productList[]. How can I?
First off, you are writing C++, this means you are lucky enough to not have to utilize C arrays/malloc'd pointers, prefer STL containers instead, since they manage the memory for you!
That said, if you want to put derived classes in a base class container, you are going to have to store pointers to that base class, once again, best to use modern C++ and use smart pointers instead, since they are self-managing and will save you the headache of free'ing them:
#include <memory> //smart pointers
#include <vector> //vector, STL container for a dynamically resizable array
#include <string> //string, pretty self explanatory
#include <algorithm> //algorithm, for powerful utility algorithms
class Cart
{
private:
int totalPrice;
// A vector of smart pointers to our base class
std::vector<std::unique_ptr<Product>> productList;
public:
Cart() = default;
void addProduct(std::unique_ptr<Product>&& product)
{
// we put our product in the cart using [Move Semantics][1], transferring ownership
// of the pointer to the cart.
productList.push_back(std::move(product));
}
void removeProduct(std::string_view product_name)
{
//we use a combination of std::find_if, from the algorithm header, together with a
//lambda, to remove a product by its name (similar functions can be written using
//different attributes as keys
auto const& to_remove = std::find_if(productList.begin(), productList.end(),
[
&product_name
](auto const& product)
{
return product->getName() == product_name;
}
);
//if we have found our product, we remove it...
if (to_remove != productList.end())
{
productList.erase(to_remove);
}
}
// return a const reference to the productList, this way we can iterate
// over the lists from outside the class without modifying it.
std::vector<std::unique_ptr<Product>> const& getProductList() const
{
return productList;
}
// add other methods, like getTotalPrice() etc...
};
At first, the solution might seem a bit overwhelming since it's so different from C, but once you familiarize yourself with the STL and these more advanced constructs (such as lambdas) you will be writing safer code, faster.
from here, an example of usage of this class can be:
#include <iostream>
int main()
{
Cart cart;
cart.addProduct(std::make_unique<Product>(10, "Apple"));
cart.addProduct(std::make_unique<Product>(20, "Banana"));
cart.addProduct(std::make_unique<Product>(30, "Orange"));
cart.removeProduct("Banana");
//modern range based for loop on the returned const reference
for(auto const& product : cart.getProductList())
{
std::cout << product->getName() << " " << product->getPrice() << std::endl;
}
return 0;
}

How to prevent a unordered_map of shared pointers from leaking?

I am building a console application in wich I am only using smart pointers. I made the choice to only use smart pointers to learn when to use which smart pointer. In this application, I am trying to use a state pattern to switch between the different states. The base class is TurnState from this class all the other state-classes inherit.
In the gamecontroller, I have defined the current state. For switching between the states I want to use an unordered_map with an enum as key and the state class as value. But as soon as I wrote down std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>> _turn_states_map; inside the header I got some memory leaks.
To get rid of those memory leaks I tried to destroy them in the deconstructor like this:
GameController::~GameController()
{
for (std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>>::iterator iterator{ _turn_states_map.begin() }; iterator != _turn_states_map.end(); iterator++) {
iterator->second.reset();
_turn_states_map.erase(iterator);
}
_turn_states_map.clear();
}
But that did not work out either. I was able to solve it using raw pointers but that is not what I am trying to achieve. So my question is, how do I delete a map with shared_ptrs in the correct way?
All help will be appreciated.
Edit 1 - Minimal example
The Game Controller will be used for holding a shared_ptr to the current state and switching to the next one.
Below is the GameController header:
class GameController
{
public:
GameController();
~GameController();
void do_action(Socket& client, Player& player, std::string command);
void set_next_state(TurnStateEnum state);
private:
std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>> _turn_states_map;
std::shared_ptr<TurnState> _turn_state;
void initialize_turn_states_map();
};
Below is the GameController source:
GameController::GameController()
{
initialize_turn_states_map();
_turn_state = _turn_states_map.at(TurnStateEnum::SETUP);
}
GameController::~GameController()
{
for (std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>>::iterator iterator{ _turn_states_map.begin() }; iterator != _turn_states_map.end(); iterator++) {
iterator->second.reset();
_turn_states_map.erase(iterator);
}
_turn_states_map.clear();
}
void GameController::do_action(Socket& client, Player& player, std::string command)
{
_turn_state->do_turn(client, player, command);
}
void GameController::set_next_state(TurnStateEnum state)
{
_turn_state = _turn_states_map.at(state);
}
void GameController::initialize_turn_states_map()
{
_turn_states_map.insert(std::make_pair(TurnStateEnum::SETUP, std::make_shared<SetupState>(*this)));
}
The TurnState is the base class. This class should contain the current logic/behaviour of the application.
Below the TurnState header:
class GameController;
class TurnState
{
public:
TurnState(GameController& gameCtrl);
virtual ~TurnState();
void next_state(TurnStateEnum stateEnum);
virtual void do_turn(Socket& client, Player& player, std::string command) = 0;
protected:
GameController& _gameCtrl;
};
Below the TurnState source:
TurnState::TurnState(GameController& gameCtrl) : _gameCtrl ( gameCtrl )
{
}
TurnState::~TurnState()
{
}
void TurnState::next_state(TurnStateEnum stateEnum)
{
_gameCtrl.set_next_state(stateEnum);
}
Setup State does not have any other variables or methods than his base class and for now, the methods are empty.
Edit 2 - Minimal example v2
This might be a better minimal example. I created a console project and uploaded it to: https://ufile.io/ce79d
There are no leaks in your program. You are using std::shared_ptr correctly. There are no circular references to fix. Although the destructors were redundant, they were harmless.
You are just not using _CrtDumpMemoryLeaks() right. You are calling it before destructors for local objects in main are run. Naturally it will report memory allocated by these objects as leaks.
To fix:
int main(int argc, const char * argv[])
{
(
GameController gameCtrl = GameController();
gameCtrl.do_action("test");
}
_CrtDumpMemoryLeaks();
return 0;
}

c++ generic storage and retrieval of objects using string handle

What would be the elegant and simple way (if exists) to implement a storage of generic objects (all other objects inherit from base). Once the object is stored, use a string handle to retrieve object or copy into another.
class Object{
public:
Object(){};
~Object(){};
};
class ObjectHandler{
public:
ObjectHandler(){};
~ObjectHandler(){};
void InsertObject(std::string handle, std::shared_ptr<Object> obj){
// some things happen before inserting
_obj.insert(std::make_pair(handle,obj));
}
std::shared_ptr<Object> RetrieveObject(std::string handle){
// some things happen before retrieving
return _obj[handle];
}
private:
std::map<std::string,std::shared_ptr<Object>> _obj;
}
For example, user defined classes are
class Dog : public Object{
public:
Dog(){};
Dog(std::string name){dogName=name};
~Dog(){};
std::string dogName;
//...
}
class Cat : public Object{
public:
Cat(){};
Cat(std::string name){catName=name};
~Cat(){};
std::string catName;
//...
}
And the following code is executed
void main(){
ObjectHandler oh;
Cat c("kitten"), cc;
Dog d("doggy"), dd;
oh.InsertObject("cat#1",c);
oh.InsertObject("dog#1",d);
cc = oh.RetrieveObject("cat#1");
dd = oh.RetrieveObject("dog#1");
std::cout << cc.catName << std::endl; // expect to print 'kitten'
std::cout << dd.dogName << std::endl; // expect to print 'doggy'
}
I believe there should be some well established idea (pattern) to make this working right.
I also suspect std::shared_ptr might be useful here.
Thanks,
I would exercise caution here, in your example you're storing your objects as Object strictly (on the stack), since that would only allocate enough space for something of type Object, should you insert something that inherits from the type, it would have the part that describes the subclass sliced.
Good examples of the problem at hand:
http://www.geeksforgeeks.org/object-slicing-in-c/
What is object slicing?
One way to get around the problem is to handle pointers to the objects in your ObjectHandler instead, the objects themselves allocted on the heap.
If I'm just misinterpreting your post, then I apologise.
But if you as you said, will store smart pointers to the object instead, making a pair should look something like this:
std::map<std::string,std::shared_ptr<Object>> _obj;;
std::string handle = "hello"; //Or whatever the actual handle is.
std::shared_ptr<Object> keyvalue(new Object());
objects[handle] = std::shared_ptr<Object>(keyvalue); //alternative to std::make_pair
objects.insert(std::make_pair(handle, std::shared_ptr<Object>(keyvalue))); //this also works
Depending on at what point you want to start handling objects with smart pointers, insertion might look like:
void InsertObject(std::string handle, Object* obj){
_obj.insert(std::make_pair(handle,std::shared_ptr<Object>(obj)));
}
std::string key("hi");
InsertObject(key, new Object());
or alternatively just:
void InsertObject(std::string handle, std::shared_ptr<Object> obj){
_obj.insert(std::make_pair(handle, obj));
}
Also note that std::map's indexing operator[] overwrites the old value if it exists, while the insert you're already using will only insert if the old one doesn't exist.

Using a std::vector<std::unique_ptr>> to another class / function

I'm having some trouble refactoring a class that uses a std::vector of unique_ptrs. I currently have a class similar to:
class DataItemA
{
// various data members
};
class DataItemB
{
// various data members
};
class PointerOwner
{
public:
PointerOwner();
~PointerOwner();
void ComplexCalculationOnItemA()
{
for (auto itr = aItemsIOwn.begin(); itr != aItemsIOwn.end(); ++itr)
{
DataItemA& itemA= (**itr);
// complex calculations that also reference DataItemB items
}
}
// methods to add / remove items from the collections
private:
// This class owns the DataItems and control their lifetime.
// The objects cannot live outside of this instance.
std::vector<std::unique_ptr<DataItemA>> aItemsIOwn;
std::vector<std::unique_ptr<DataItemB>> bItemsIOwn;
};
I was refactoring the class to extract the complex calculation to another class and was unsure how to pass the vector of unique_ptrs to the other class and clearly 'state' that the calculation does not own the pointers. Is it reasonable to:
class ComplexItemAProcessor
{
ComplexItemAProcessor(const std::vector<std::unique_ptr<DataItemA>>& itemsToProcess)
{
// can I store the itemsToProcess in a member variable
}
SomeReturnType runCalcuation() {}
private:
// store the reference to calculation
}
Or is this better which can be done:
class ComplexItemAProcessor
{
ComplexItemAProcessor()
{
}
SomeReturnType runCalcuation(const std::vector<std::unique_ptr<DataItemA>>& itemsToProcess)
{
// process the collection as per original class
}
}
The lifetime of the ComplexItemAProcessor would be limited to scope of the original method.
class PointerOwner
{
public:
PointerOwner();
~PointerOwner();
ComplexCalculationOnItemA()
{
ComplexItemAProcessor processor; /** ? pass here **/
SomeReturnType result = processor.runCalcuation(/* ? pass here */);
}
private:
// This class owns the DataItems and control their lifetime.
// The objects cannot live outside of this instance.
std::vector<std::unique_ptr<DataItemA>> aItemsIOwn;
std::vector<std::unique_ptr<DataItemB>> bItemsIOwn;
};
Is either of these better than the other? Neither feels right to me, but that could be my limited experience with smart pointers in general. Is there another way for another class to process the vector without transferring ownership?
I don't think I need shared_ptrs as PointerOwner is the only owner.

Trying to store objects in a vector

I'm quite new to C++ and I am trying to store objects inside a std::vector like this:
Event.h:
//event.h
class Event
{
public:
Event();
Event(std::string name);
~Event();
void addVisitor(Visitor visitor);
private:
std::vector<Visitor> m_visitors;
};
Event.cpp:
//event.cpp
Event::Event() :
m_name("Unnamed Event")
{
}
Event::Event(std::string name) :
m_name(name)
{
}
void Event::addVisitor(Visitor visitor)
{
this->m_visitors.push_back(visitor);
}
void Event::listVisitors()
{
std::vector<Visitor>::iterator it;
for(it = this->m_visitors.begin();it != this->m_visitors.end(); ++it)
{
std::cout << it->getName() << std::endl;
}
}
Visitor.h:
//visitor.h
class Visitor
{
public:
Visitor();
Visitor(std::string name);
~Visitor();
std::string getName() const;
void listVisitors();
private:
std::string m_name;
};
Visitor.cpp:
//visitor.cpp
Visitor::Visitor() :
m_name("John Doe")
{
}
Visitor::Visitor(std::string name) :
m_name(name)
{
}
std::string Visitor::getName() const
{
return m_name;
}
main.cpp:
//main.cpp
int main()
{
Event *e1 = new Event("Whatever");
Visitor *v1 = new Visitor("Dummy1");
Visitor *v2 = new Visitor("Dummy2");
e1->addVisitor(*v1);
e1->addVisitor(*v2);
}
If I do it like this I would have to add a copy constructor which would make a deep copy so the object gets copied properly into the vector. I'm looking for a way around it by only storing pointers to the objects in a vector.
I already tried it with std::vector<std::unique_ptr<Visitor> > m_visitors, but then I got some errors when calling addVisitor in main.cpp. Of course I changed the declaration of the class members accordingly.
How would an appropriate declaration of the members and the member function look like to make it work?
Stylistically, if you are passing pointers, just accept pointers as the function arguments.
What's happening in the example code above is that the visitors are getting copied to become function arguments and the pointers you had are unreferenced by anything outside of the main function.
I can't speak to what the errors are that you're seeing as you didn't describe them but it probably has to do with incompatible types.
Just get rid of the news because for these data structures they're unnecessary.
int main()
{
Event e1("Whatever");
Visitor v1("Dummy1");
Visitor v2("Dummy2");
e1.addVisitor(v1);
e1.addVisitor(v2);
}
I would suggest that if you don't know how to use pointers you couldn't possibly want to store them instead (they're a hassle IMO to store in the vector when copying by value works just fine).
The compiler generated copy constructor should work just fine.
No manual deep copy required, because you are quite correctly using std::string, which supports RAII.
However, your main function has three memory leaks — there is no need to use new there anyway, so simply don't.
General rule of thumb:
If, at any time T, you're thinking of introducing more pointers into your code, then you're probably going in the wrong direction.