我尽可能地简化了代码。 所以我有两节课:
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{};
};
和
class System
{
public:
void loadEntities(std::shared_ptr<std::vector<Entity> > entities)
{
m_entities = entities;
}
private:
std::shared_ptr<std::vector<Entity> > m_entities;
};
现在基本上我希望系统的m_entities指向EntityManager的m_entities。
我这样做了:
system = System();
system.loadEntities(m_entityManager.getEntities());
但后来我将一个元素推回到EntityManager的m_entities向量中,并且这个元素没有添加到System的m_entities向量中,这意味着我的指针没有指向。
我的错误在哪里?
谢谢!
答案 0 :(得分:2)
您的问题就在这一行:return std::make_shared<std::vector<Entity> >(m_entities);
正在发生的事情是shared_ptr
管理一个新的std::vectory<Entity>
容器,该容器初始化为m_entities
的副本。因此,修改shared_ptr
中的实例不会修改EntityManager
类中的数据成员,当然shared_ptr
也不会看到对EntityManager::m_entities
所做的更改。< / p>
答案 1 :(得分:2)
std::make_shared
不会“让这个东西分享”;它“会让人分享”。
所以,你不能只是指出一个指向已经存在的东西的共享指针。
您的代码会动态分配来自std::vector
的{{1}},副本构建,并由m_entities
管理。这是简写:
std::shared_ptr
目前还不清楚你要做什么,从(你自己承认)没有实现这个目标的代码。但std::vector<Entity>* ptr_to_copy = new std::vector<Entity>(m_entities);
return std::shared_ptr(ptr_to_copy);
似乎不太适合。
如果是,则从开始动态分配和共享向量;否则,只需返回对矢量的引用。
答案 2 :(得分:0)
Hack无指针解决方案的示例。
#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();
}
这是一个黑客。这只是一个黑客。
如果您想EntityManager
权限,请参阅Writing your own STL Container以获取提示。如果你想要所有的花里胡哨,这项工作相当复杂。根据您使用EntityManager
的方式以及Entity
管理逻辑的复杂程度,您可能最好放弃EntityManager
并使用简单的旧版std::vector
。
附录:What is meant by Resource Acquisition is Initialization (RAII)?