W jakim celu powinienem użyć std::get_temporary_buffer
? Standard mówi, co następuje:
Uzyskuje wskaźnik do pamięci wystarczającej do przechowywania do n sąsiadujących obiektów T.
Myślałem, że bufor zostanie przydzielony na stosie, ale to nieprawda. Zgodnie ze standardem C ++ ten bufor w rzeczywistości nie jest tymczasowy. Jakie zalety ma ta funkcja w stosunku do funkcji globalnej ::operator new
, która również nie konstruuje obiektów. Czy mam rację, że poniższe stwierdzenia są równoważne?
int* x;
x = std::get_temporary_buffer<int>( 10 ).first;
x = static_cast<int*>( ::operator new( 10*sizeof(int) ) );
Czy ta funkcja istnieje tylko dla cukru składniowego? Dlaczego jest temporary
w jego nazwie?
Jeden przypadek użycia został zasugerowany w Dr Dobb's Journal, 1 lipca 1996, dla implementacji algorytmów:
Jeśli żaden bufor nie może zostać przydzielony lub jeśli jest mniejszy niż żądany, algorytm nadal działa poprawnie, po prostu zwalnia.
std::get_temporary_buffer
zostanie wycofane w C ++ 17.Odpowiedzi:
Stroustrup mówi w „The C ++ Programming Language” ( §19.4.4 , SE):
Rozpoczyna również wprowadzenie do obu funkcji od:
... ale wydaje się, że nigdzie nie ma definicji tymczasowego ani długoterminowego .
Anegdota w „Z matematyki Generic Programming” wspomina, że Stepanov dostarczył fałszywe realizację zastępczy w pierwotnym projekcie STL, jednakże:
źródło
operator new
z coraz mniejszymi argumentami, aż do pomyślnego przydzielenia. Nie ma tam żadnych specjalnych optymalizacji.crazy_allocator
get_temporary_buffer
. Jeśli jednak otrzymamy kwotę mniejszą niż żądana (a szkoda), staramy się nadal pracować z magazynem, który mamy. Może być lepsze niż przechwytywaniebad_alloc
wyjątków spowodowanych próbą przydzielenia większej ilości pamięci niż jest dostępna. Jednak prawdziwa użyteczność pozostaje i spada przy dobrej implementacji.Bibliotekarz Microsoftu mówi co następuje ( tutaj ):
źródło
Norma mówi, że przydziela miejsce na maksymalnie
n
elementy. Innymi słowy, twój przykład może zwrócić bufor wystarczająco duży dla tylko 5 obiektów.Wydaje się jednak, że trudno sobie wyobrazić dobry przypadek użycia tego. Być może, jeśli pracujesz na platformie z bardzo ograniczoną pamięcią, jest to wygodny sposób na uzyskanie „jak największej ilości pamięci”.
Ale na takiej ograniczonej platformie wyobrażam sobie, że ominiesz alokator pamięci tak bardzo, jak to możliwe, i użyjesz puli pamięci lub czegoś, nad czym masz pełną kontrolę.
źródło
Funkcja jest przestarzała w C ++ 17, więc poprawna odpowiedź brzmi teraz „bez celu, nie używaj jej”.
źródło
ptrdiff_t request = 12 pair<int*,ptrdiff_t> p = get_temporary_buffer<int>(request); int* base = p.first; ptrdiff_t respond = p.sencond; assert( is_valid( base, base + respond ) );
odpowiedź może być mniejsza niż prośba .
size_t require = 12; int* base = static_cast<int*>( ::operator new( require*sizeof(int) ) ); assert( is_valid( base, base + require ) );
rzeczywisty rozmiar podstawy musi być większy lub równy wymaganiom .
źródło
Być może (tylko przypuszczenie) ma to coś wspólnego z fragmentacją pamięci. Jeśli nadal będziesz w dużym stopniu alokować i zwalniać pamięć czasową, ale za każdym razem, gdy to robisz, przydzielasz jakąś długoterminową zamierzoną pamięć po przydzieleniu temp, ale przed jej zwolnieniem, możesz skończyć z pofragmentowaną stertą (tak sądzę).
Więc get_temporary_buffer może być zaprojektowany jako większy niż byś potrzebował fragment pamięci, który jest przydzielany raz (być może jest wiele fragmentów gotowych do zaakceptowania wielu żądań), a za każdym razem, gdy potrzebujesz pamięci, po prostu dostajesz jedną z kawałki. Więc pamięć nie ulega fragmentacji.
źródło