在对象超出作用域之前调用析构函数
Destructor Called Before Object Goes Out Of Scope
所以我已经清理了一些代码,并且我注意到类的构造函数被调用后直接调用了构造函数。实际上,对象什么也不做。我很确定对象仍然在作用域中,因为我仍然可以访问它的成员。在构造函数中,我输出了this
,在析构函数中,我输出了"deleted: " << this
。下面是输出的内容:
x7fff5fbff380
0x7fff5fbff3d0
deleted: 0x7fff5fbff3d0
deleted: 0x7fff5fbff380
0x7fff5fbff280
0x7fff5fbff2d0
deleted: 0x7fff5fbff2d0
deleted: 0x7fff5fbff280
0x7fff5fbff190
0x7fff5fbff1e0
deleted: 0x7fff5fbff1e0
deleted: 0x7fff5fbff190
显然,这不足以帮助解决问题,所以这里有一些代码,涉及如何创建对象,如何使用对象以及如何销毁对象。
//event listener constructor
EventListener::EventListener(EventTypes typeEvent,EventFunction functionPointer)
{
this->typeEvent = typeEvent;
this->functionPointer = functionPointer;
//add it to the tick handler
this->listenerID = EngineEventDispacher.addEventListener(this);
std::cout << this << std::endl;
}
void EventListener::removeListener()
{
//remove it from the tickHandler
EngineEventDispacher.removeEventListener(this->listenerID);
}
//we add the event listener here
int EventDispatcher::addEventListener(EventListener* listener)
{
EventListeners.push_back(listener);
return (int)EventListeners.size() - 1;
}
//get rid of a listener
void EventDispatcher::removeEventListener(int id)
{
//std::vector<EventListener*>::iterator it;
//it = EventListeners.begin() + id;
//EventListeners.erase(it);
// EventListeners.shrink_to_fit();
//this isnt very memory efficiant, but it is the best solution for the CPU
EventListeners[id] = nullptr;
}
//send an event to all the listeners that can have it
void EventDispatcher::dispatchEvent(EventTypes eventType, Event* event)
{
for (int i = 0; i < EventListeners.size(); i++)
{
//we check if the current listener is subscribed to the event we are calling
if (EventListeners[i] != nullptr)
if (EventListeners[i]->typeEvent == eventType && EventListeners[i]->functionPointer != 0 )
{
//it was subscribed, so we are going to call it
EventListeners[i]->functionPointer(event);
}
}
}
//make sure that we can't call this
EventListener::~EventListener()
{
EngineEventDispacher.removeEventListener(this->listenerID);
std::cout << "deleted: " << this << std::endl;
}
类的样子:
//This will recive events
class EventListener
{
//this is what type of event it will repsond to
public:
EventTypes typeEvent;
EventListener(EventTypes typeEvent, EventFunction);
EventListener();
~EventListener();
EventFunction functionPointer;
void removeListener();
private:
int listenerID;
};
//her we define the event dispatcher
class EventDispatcher
{
public:
int addEventListener(EventListener*);
void removeEventListener(int);
void dispatchEvent(EventTypes, Event*);
private:
std::vector<EventListener*>EventListeners;
};
最后是如何声明和构造事件侦听器:
class Scene
{
public:
Scene();
std::vector<StaticGeometry>GameObjects;
void addStaticGeometry(StaticGeometry object);
void renderSceneWithCamera(camera cam);
void renderSceneWithCameraAndProgram(camera cam,GLuint program);
void pickObjectFromScene();
void pickObjectFromSceneWithScreenCoords(int x, int y);
int selectedObject;
private:
//listen for the left click
EventListener leftClickEventListener;
void leftClick(Event* eventPtr);
};
Scene::Scene() : leftClickEventListener(EventTypeLeftMouseClick,std::bind(&Scene::leftClick,this,std::placeholders::_1))
{
//default constructor, we just need to make sure that the selected thing is -1
selectedObject = -1;
}
据我所知,成员不应该在父类调用其解构函数之前调用解构函数。Scene类绝对没有调用它的重构器,这才是真正让我困惑的。一切都应该很好,但事实并非如此。我没有发现任何东西应该随机地决定解构自己。任何帮助都会很感激。谢谢。
问题:
如果您在块或函数中创建具有自动存储时间的对象,如
{
// ...
EventListener myListener();
// ...
}
对象将在执行离开块/函数后立即销毁,即使它仍然可以从其他地方引用。参见:
创建对象:带或不带' new '
一般情况下,永远不要将指针传递给具有这种作用域的对象,只要它可能存储在内部。
解决方案:
如果你想让你的对象驻留在当前块之外,你必须显式地使用new
:
{
// ...
EventListener* myListener = new EventListener();
// ...
}
我很确定对象仍然在作用域中,因为我可以访问它成员。
注意:即使对象被(隐式)销毁,指向对象的指针仍然可能看起来是可用的,但是对该指针的解引用是一个严重的错误,尽管并不总是明显的。
相关文章:
- 什么时候调用析构函数
- C++-明确何时以及如何调用析构函数
- C++ 防止在映射中放置()时调用析构函数
- 调用析构函数以释放动态分配的内存
- C++:使用方法调用析构函数的顺序是什么?
- 向量推回调用析构函数时调用析构函数
- 如何在调用析构函数时优雅地停止/销毁带有阻塞调用C++线程?
- C++,我应该调用析构函数吗?
- 如何获取有关在 Clang LibTooling 中调用析构函数的信息?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 为什么这里不调用析构函数
- 在调用 std::bind 的产品后意外调用析构函数
- 为什么在传递给函数而不是构造函数时调用析构函数?
- 如何在C++中调用析构函数
- 为什么为未删除的对象调用析构函数?
- 调用析构函数时出错
- C++ 在不释放内存的情况下调用析构函数
- 为什么在运算符删除中不调用析构函数?
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- 在 postOrderDelete 上调用析构函数时引发的异常