这是我的问题,我说我有一个函数,它由以下内容组成:
void function() {
entity e; //entity is just a class
entities.push_back(e); //entities is a vector of entity objects
}
Run Code Online (Sandbox Code Playgroud)
这有什么麻烦我.'e'包含指向另一个对象的指针.当调用实体的析构函数时,它会删除该指针.由于'e'和实体中的实体都指向同一个地方,如果我对来自实体的指针执行某些操作(在函数外部)它会产生错误,因为只要函数删除指针就会被删除回.解决这个问题的最佳方法是什么?
C++是一种"基于副本"的语言,例如,容器中Entity确实会将您提供的实体的副本放在容器中.
复制是在很多地方用C++制作的,所以你的班级要么正确支持它们要么完全禁止它们.
您的类包含指向其他数据的指针:当您复制该类的实例时会发生什么?如果复制指针没问题,那么很明显,删除析构函数中的指向对象是不行的,因为仍然存在的副本将指向已删除的对象.
有一个简单的规则可以帮助避免这种错误,被称为"三个规则".如果您已明确编码
在你的课堂上,很可能你需要他们三个.
在这种情况下,您有一个非默认的析构函数(因为删除了指向的对象),因此您还需要告诉复制构造或赋值时要执行的操作.
如果您希望该类不可复制,那么请确保
struct Entity {
Object *o;
Entity(Object *o) : o(o) {
...
}
~Entity() {
delete o;
}
private:
// Taboo... this should just never happen!!!
// Here is a declaration, but no implementation will be written
Entity(const Entity& other); // Copy constructor
Entity& operator=(const Entity&); // Assignment
};
Run Code Online (Sandbox Code Playgroud)
声明禁止的操作private将确保用户代码永远不会调用它们(这将是一个编译时错误),只是声明它们而不提供实现将确保即使是类代码本身也不会错误地调用它们(你会得到它们)链接时错误).
但是,在这种特定情况下,这将禁止您的代码将Entity实例放入容器中(必须复制容器内的元素).你可以将Entity 指针放在一个容器中(指针可以被复制,因此std::vector<Entity *>for entities是合法的)但是你将负责处理对象的正确生命周期(谁应该调用析构函数以及何时应该发生?).
另一方面,如果您有一个指向类中数据的指针,并且您希望允许复制该类的实例,您可以:
对于第二种解决方案,常见的方法是使用"引用计数"指针,即指向数据"知道"有多少指针引用它并且仅在该计数达到0时被销毁.