Umiejscawiający operator new a operator delete

0

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 ?

0

Dlaczego ma byc bledny ? Wszystko jest ok alokujesz sobie jeden bajt na stercie i deletem zwalniasz, nie widze zadnego problemu.

0

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.

0

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");
}

0

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.

0

Czyli dla powyższego kodu można jedynie zwolnić cały obszar instrukcją:

delete [] m

Czy istnieje jeszcze jakieś inne rozwiązanie?

0

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:

  • skoro czas zycia miejsca w pamieci jest logicznie ODERWANY od czasu zycia instancji obiektu
  • nie mozna uzywac normalnego delete ani delete[] na tych obiektach, gdyz niszczac obiekt NIE chcesz niszczyc miejsca w pamieci
  • chcesz zniszczyc tylko obiekt
  • dlatego wiec, na obiekcie, masz recznie wywolac destruktor Klasy, a NIE operator DELETE (ktory wola .dtor i zwalnia pamiec)!!:
     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 :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1