在对象超出范围之前调用的析构函数

时间:2014-07-23 09:01:33

标签: c++ scope destructor

所以我一直在清理一些代码,我注意到在调用constructer之后直接调用了类的析构函数。实际上,该对象什么都不做。我很确定该对象仍然在范围内,因为我仍然可以访问其成员。在构造函数中,我打印出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类绝对没有调用它的重构器,这就是让我困惑的东西。一切都应该没问题,但事实并非如此。我发现的任何东西都说不应该随意决定解构自己。任何帮助,将不胜感激。感谢。

1 个答案:

答案 0 :(得分:1)

问题:

如果您在具有自动存储持续时间的块或函数内创建对象,例如

{
  // ...
  EventListener myListener();
  // ...
}

一旦执行离开块/函数,对象将被销毁,即使它仍然可以从其他地方引用。另见:

Creating an object: with or without `new`

通常,您不应该将指针传递给具有此类范围的对象,而是指向可能存储在内部的任何位置。

解决方案:

如果您希望对象超出当前块,则必须明确使用new

{
  // ...
  EventListener* myListener = new EventListener();
  // ...
}

  

我很确定该对象仍在范围内,因为我可以访问它   成员们仍然。

注意:即使在(隐式)销毁对象之后,指向对象的指针仍然似乎可用,但解除引用此指针是一个严重的,但并不总是很明显的错误。< / p>