Как удалить объект, который создается внутри локальной функции в C ++? - PullRequest
3 голосов
/ 19 июля 2011

Я объясню сценарий на примере.

   void func()
   {
          CLine* pObj = new CLine();
   }
   void func2()
   {
   }

Как удалить объект CLine в func2 ()?Возможно ли это?

Спасибо

Ответы [ 6 ]

13 голосов
/ 19 июля 2011

Это невозможно.Как только func заканчивается, вы теряете все ссылки на pObj и пропускаете его память.

3 голосов
/ 19 июля 2011

В этом случае, вероятно, вообще нет необходимости использовать переменную, размещенную в свободном хранилище. Просто сделай:

void func()
{
       CLine obj;
}
void func2()
{
}

obj будет автоматически уничтожено в конце области действия.

Если переменная обязательно должна быть размещена в хранилище, вы можете поместить ее в unique_ptr следующим образом:

void func()
{
       const std::unique_ptr<CLine> obj(new CLine());
}
void func2()
{
}

если вы используете c++03, просто замените unique_ptr на auto_ptr.

В любом случае, если вы действительно должны использовать код точно так же, как в вашем примере, тогда - это способ удалить объект CLine. Вы должны использовать перегруженный оператор new и оператор delete. Это должно быть что-то вроде:

#include <vector>
#include <new>
#include <algorithm>
struct CLine {
    //... Other members ...

    static std::vector<void*> pointerCache;

    void* operator new(std::size_t size) throw(std::bad_alloc) {
        while (true) {
            void* pointer(malloc(size));
            if (pointer) {
                try {
                    pointerCache.push_back(pointer);
                    return pointer;
                }
                catch (std::bad_alloc&) {
                    free(pointer);
                }
            }
            if (std::new_handler handler = std::set_new_handler(0)) {
                std::set_new_handler(handler);
                (*handler)();
            }
            else {
                throw std::bad_alloc();
            }
        }
    }

    void operator delete(void *p) throw() {
        pointerCache.erase(std::remove(pointerCache.begin(), pointerCache.end(), p),pointerCache.end());
        free(p);
    }

    void* operator new(std::size_t size, std::nothrow_t const&) throw() {
        try {
            return operator new(size);
        } catch (std::bad_alloc&) {
            return 0;
        }
    }
    //Compressed for space constraints.
    void operator delete(void *p, std::nothrow_t const&) throw(){
        operator delete(p);}
    void* operator new[](std::size_t size) throw(std::bad_alloc){
        return operator new(size);}
    void operator delete[](void *p) throw(){operator delete(p);}
    void* operator new[](std::size_t size, std::nothrow_t const& nothrow) throw(){
        return operator new(size, nothrow);}
    void operator delete[](void *p, std::nothrow_t const& nothrow) throw(){
        operator delete(p, nothrow);}
};
std::vector<void*> CLine::pointerCache;

И тогда ваш код может выглядеть так:

void func()
{
    CLine* pObj = new CLine();
}
void func2()
{
    //The most recently added pointer in CLine::pointerCache is
    // the one that was added in func()
    delete static_cast<CLine*> (CLine::pointerCache.back());
}

int main()
{
    func();
    func2();
}    

Но на самом деле, в этом коде так много неправильного, что вам было бы лучше просто изменить свой дизайн. Вот некоторые из проблем: полная путаница, которую вы будете вызывать у людей, читающих ваш код, отсутствие безопасности потоков и использование глобального объекта pointerCache.

1 голос
/ 19 июля 2011

Да, вы можете.

void func()
{
     CLine* pObj = new CLine();
}

void func2(CLine* pObj)
{
     delete pObj;
}

если передать указатель CLine в func2

1 голос
/ 19 июля 2011

Это возможно, если func () и func2 () являются методами одного и того же класса, а pObj является переменной-членом этого класса. Я понимаю, что это не то, как вы структурировали свой вопрос, но это один из способов получить эффект, который вы ищете

class MyClass
{
    CLine* pObj;

     void func()
     {
          pObj = new CLine();
     }
     void func2()
     {
         delete pObj;
     }
}
0 голосов
/ 19 июля 2011

Вы должны удалить созданный вами объект динамически в функции внутри самой функции.Если вы выйдете из функции, не удалив ее, вы не сможете удалить ее, и память будет потеряна.

0 голосов
/ 19 июля 2011

Нет, это невозможно. Поскольку единственная копия указателя теряется, когда func выходит из области видимости, у вас больше нет ссылки на память для использования с operator delete.

...