我已经尽可能地简化了代码。所以我有两个类:
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向量中,这意味着我的指针没有指向。
我的错误在哪里?
谢谢!
发布于 2016-07-07 02:29:01
您的问题是这一行:return std::make_shared<std::vector<Entity> >(m_entities);
发生的事情是,shared_ptr管理一个新的std::vectory<Entity>容器,该容器被初始化为m_entities的副本。因此,在shared_ptr中修改实例不会修改EntityManager类中的数据成员,当然,shared_ptr也不会看到对EntityManager::m_entities所做的更改。
发布于 2016-07-07 02:36:59
std::make_shared不是“让这个东西被分享”,而是“让一个东西被分享”。
所以,你不能无中生有地创建一个指向已经存在的东西的共享指针。
您的代码动态分配一个从m_entities构造并由std::shared_ptr管理的std::vector副本。这是对此的简写:
std::vector<Entity>* ptr_to_copy = new std::vector<Entity>(m_entities);
return std::shared_ptr(ptr_to_copy);不清楚你想要做什么,因为代码(你自己承认)并没有达到这个目标。但std::shared_ptr似乎不太可能适合这里。
如果是,则从一开始就动态分配和共享该向量;否则,只返回对该向量的引用。
发布于 2016-07-07 04:21:38
无指针解决方案的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)?
https://stackoverflow.com/questions/38231160
复制相似问题