2013-07-15 3 views
0

Я хочу определить свое собственное место размещения и удаление места (принимая дополнительные параметры), и я обнаружил, что могу правильно вызвать место размещения, в то время как я не смог получить доступ к удалению места размещения. Может ли кто-нибудь сказать мне, я неправильно определяю место размещения, или я вызываю его неправильно?C++ самоопределяемое место размещения new и размещение delete invoking

class A 
{ 
public: 
    A(int a) : a(a){} 

    static void* operator new(std::size_t, int); // the placement new 
    static void operator delete(void*, int)throw(); // the corresponding placement delete 
private: 
    int a; 
}; 

void* A::operator new(std::size_t size, int n) 
{ 
    std::cout << "size: " << size << " " << "n: " << n << std::endl; 
    return ::operator new(size); 
} 

void A::operator delete(void* p, int n)throw() 
{ 
    std::cout << "n: " << n << std::endl; 
    ::operator delete(p); 
} 

int main(int argc, char* argv[]) 
{ 
    A* a = new(10) A(100); 

    std::cout << std::endl; 

    delete(4) a; // error???????????????????, but how? 

    return 0; 
} 
+0

Возможный дубликат [Почему нет места удаления в C++?] (Http://stackoverflow.com/questions/5857240/why-there-is-no-placement-delete-expression-in-c) – Suma

+0

Это не похоже на размещение нового, особенно на то, как вы указали свой указатель 'A *' (не уверен, что 10 - это правильная ячейка памяти: P). Взгляните сюда: http://www.parashift.com/c++-faq/placement-new.html – Xaqq

+1

@Xaqq: * * * форма размещения новая, но не самая распространенная, которая проходит по адресу, где объект будет размещен. –

ответ

3

delete Размещение доступно только для обработки исключений, которые возникают во время проведения оценки в new выражении размещения. Если конструкция завершается успешно, то позже будет использоваться нормальный delete.

Вы можете вызывать функцию освобождения места размещения явно, но она не будет иметь такое же поведение, как оператор delete (он не будет автоматически вызывать деструктор).

В вашем случае, соответствующий код будет:

a->~A(); 
A::operator delete(a, 4); 

Тьфу!

Для массивов это еще хуже, потому что вы не можете получить количество элементов (и количество деструкторов для вызова) из того места, где хранился компилятор, который используется для его собственного использования.

Создайте свой перегруженный operator new так, чтобы он правильно с одним аргументом operator delete. Тогда пользователи класса могут использовать delete ptr; и std::unique_ptr т.д.

Если вам требуется пользовательский открепление, затем обертка распределения, которая возвращает std::shared_ptr с пользовательской Deleter будет лучше, чем обычай размещения нового.

+0

Это означает, что я не могу изменить подпись места удаления, и я могу только переопределить его? И когда я хочу освободить ресурс, я вызываю: a-> ~ A(); удалить a; ? – JavaBeta

+1

@JavaBeta: Нет. 'Delete a;' будет вызывать деструктор во второй раз, а затем отключить функцию удаления одного аргумента 'operator delete (void *)'. Если вы хотите вызвать другую функцию освобождения (размещения), сделайте это явно, как показывает мой ответ. Если вы можете заставить обычную функцию освобождения от работы работать правильно, пользователь вашего класса может сказать просто «delete p;» и получить как вызов деструктора, так и освобождение сразу. –

+0

О, я должен явно называть его оператором сферы? Он работает, он все еще меня смущает, так или иначе механизм размещения нового места размещения и удаления места размещения совершенно несовместим. – JavaBeta

Смежные вопросы