Mamy taki przykładowy fragment kodu:
char *miejsce = new char[10];
void *tutaj = &miejsce[4];
char *wsk = new (tutaj) char;
*wsk = 'm';
Jak teraz wobec wskaźnika wsk używać operatora delete ? Zapis
delete wsk
jest chyba błędny ?
Mamy taki przykładowy fragment kodu:
char *miejsce = new char[10];
void *tutaj = &miejsce[4];
char *wsk = new (tutaj) char;
*wsk = 'm';
Jak teraz wobec wskaźnika wsk używać operatora delete ? Zapis
delete wsk
jest chyba błędny ?
Dlaczego ma byc bledny ? Wszystko jest ok alokujesz sobie jeden bajt na stercie i deletem zwalniasz, nie widze zadnego problemu.
Błedny byłby jakbyś tam alokował jakiś obiekt z własnymi wskaźnikami wymagającymi posprzątania. W takim przypadku musiałbyś najpierw wywołać destruktor obiektu, a dopiero potem deletować miejsce.
Bibiliografia: http://www2.research.att.com/~bs/bs_faq2.html#placement-delete.
W Visual Studio 2008 poniższy fragment kodu się kompiluje, ale potem Visual wyrzuca jakieś błędy.
#include <iostream>
using namespace std;
void main()
{
char *m = new char[10];
void *p = &m[4];
char *wsk = new (p) char;
*wsk = 'd';
cout<<endl;
for(int i = 0; i < 10; i++)
{
cout<<m[i]<<endl;
}
cout<<endl;
delete wsk;
for(int i = 0; i < 10; i++)
{
cout<<m[i]<<endl;
}
cout<<endl;
system("pause");
}
No to wtopa.
W takim razie jest błedny. Usuwanie tego bedzie polegać na wywołaniu destruktora(dla char pomijamy), a potem deletować cały bufer, czyli Twoje m.
Kolejna genialna bibliografia: http://www.devx.com/cplus/10MinuteSolution/30508/1954.
Czyli dla powyższego kodu można jedynie zwolnić cały obszar instrukcją:
delete [] m
Czy istnieje jeszcze jakieś inne rozwiązanie?
A jakie inne rozwiazanie chcialbys miec? Nie ma czegos takiego jak delete lustrzany do placement-new. Placement-delete sluzy do czegos zupelnie innego, poczytaj na przykald: http://en.wikipedia.org/wiki/Placement_syntax#Placement_delete
//edit: btw. warto tez zerknac na przeciazanie operatora new/delete dla klas.. moze to jest w Twoim przypadku mozliwe i zupelnie wystarczy?
Tamże tez jest opisane, w jaki sposob "niszczy" sie obiekty konkstruowane w-miejscu:
char bufor[1000];
void* place = &bufor[128];
T* ptr = new ( place ) T(123, "mama");
ptr -> ~T(); // *PTR jest LOGICZNIE zniszczone, obiekt/klasa mialy szanse sie posprzatac swoje smieci,
T* ptr2 = new ( place ) T(321, "tata"); // miejsce w buforze teraz mozna zastapic innym obiektem
ptr -> ~T(); // *PTR jest LOGICZNIE zniszczone, obiekt/klasa mialy szanse sie posprzatac swoje smieci,
....
// a kiedys tam, kiedy juz w ogole konczymy prace, niszczymy wszytkie zalegajace/pogubione obiekty
for( idx i = ???; i< ???; i+= ???) // jakos skaczac po miejscach w buforze...
if( ???? ) // jakos sprawdzajac czy dane miejsce faktycznie jest zajete, a moze juz ktos ten obiekt sam posprzatal destruktorem..
((T*)(bufor + i)) -> ~T();
// i na koncu niszczymy sam bufor/pule pamieci
// delete[] bufor; - tutaj bezsensu, gdyz ta przykladowa byla nie-dynamiczna
Niestety musisz sam, jakos, doskonale sie orientowac czy dany wskaznik ptr* jest zwykly, czy jest Twoj-specjalny. Najprosciej --- wiesz przeciez jaki jest typ wskaznika. Jesli korzystasz ze klasy X ktora TY zarządzasz - uzywaj ja recznie. Jesli wskaznik jest na Y ktore korzysta z domyslnej alokacji - usuwaj ja normalnie. A moze mieszasz jedno z drugim i u Ciebie wskaznik X* moze byc albo taki albo siaki? w takim razie, musi z nim chodzic informacja jak byl stworzony. Sorry, nie ma bata. Jak Sobie tworzysz dynamiczna tablice char[N], to tez musi z jej char* latac jej size_t rozmiar, no chyba ze tablica ta ma jednoznaczny terminator ----- ptr* tez moze byc oznaczony jednoznacznie, wewnetrznie, ale o tym teraz Ci nie napisze, bo za gleboko trzeba by wchodzic w rozne rzeczy... powiem tylko ze mozna wykorzystac fakt, ze adresy normalnie alokowalne zwykle sa .... parzyste. Albo podzielne przez 4/8/16/etc. Zaleznie od platformy.
Najlepiej po prostu opakuj swoj super-wskaznik-na-obiekt-z-puli w jakas przezroczysta mikroklase, ala std::auto_ptr, kompilator ja wyoptymalizuje pozniej i prawie nic z niej nie zostanie.
//edit: oops.. nie przeczytalem odpowiedzi burego_pajaca :)