2009-07-02 22 views
8

Czy można przydzielić dowolny blok pamięci za pomocą operatora "nowego"? W C mogę zrobić to jak "void * p = malloc (7);" - przydzieli to 7 bajtów, jeśli wyrównanie pamięci jest ustawione na 1 bajt. Jak zrobić to samo w C++ z nowym operatorem?Alokacja pamięci w C++

Odpowiedz

43

Arbitralne bloki pamięci można przydzielić za pomocą operator new w C++; nie z operatorem new, który służy do konstruowania obiektów.

void* pBlock = ::operator new(7); 

Takie bloki można później zwolnić za pomocą operator delete.

::operator delete(pBlock); 

Zauważ, że operator new będzie przydzielona pamięć właściwie wyrównany dla dowolnego rodzaju obiektu, więc realizacja nie może przydzielić dokładnie siedem bajtów i nie więcej, ale to samo jest (zazwyczaj) prawdziwe malloc. Klienci C z poziomu malloc zwykle wymagają również pamięci wyrównanej.

+7

+1 za to, że tam jest * jest * sposobem na zrobienie tego bez malloc i za darmo :) –

+1

Należy również pamiętać, że operator new zwykle po prostu przekazuje pieniądze malloc() w każdym razie (przy każdej implementacji, o której mi wiadomo). Jak powiedział dominikański, równie dobrze mógłbym użyć malloc. –

+1

Wielkie dzięki. To jest odpowiedź (":: operator new"). Spędziłem dużo czasu próbując dowiedzieć się, dlaczego ":: new (x);" nie działa :) – user132349

8

Nie można przydzielić void wskaźnik z operatorem C++ 's new: trzeba będzie przeznaczyć wyraźny typ, takich jak char lub uint8_t:

char *p = new char[7]; 
uint8_t *q = new uint8_t[7]; 
... 
delete [] p; 
delete [] q; 
2

myślę, że może być szukasz Placement New.

+1

Dodam tylko, że jeśli zamierzasz używać takich technik, jak w nowym miejscu, musisz zachować ostrożność. Używaj go tylko wtedy, gdy jest to naprawdę konieczne! –

+5

Jak nowe miejsce docelowe dotyczy przydzielania pamięci? – avakar

+0

@Miky D: Zgadzam się, dlatego dołączona strona jest posypana słowem "NIEBEZPIECZEŃSTWO" we wszystkich wersjach. :-) –

2

nowy znak [7];

Tradycyjnie char to bajt, chociaż niektóre biblioteki mogą zawierać typ BYTE.

+5

Nie ma znaczenia; char to najmniejszy typ, jaki może obsłużyć implementacja. Jeśli znak jest 16-bitowy, to typ bajtu nie może być mniejszy niż 16-bitowy. Pamiętaj, że sizeof (char) == 1. Zawsze. –

+0

@ David Thornley: sizeof (char) nie jest konieczne 1, w przeciwnym razie wszystkie rodzaje bibliotek rozrządowych będą strasznie zdenerwowane. – florin

+1

@florin: sizeof (char) == 1 zgodnie ze standardem. Patrz sekcja 5.3.3 normy ISO/IEC 14882: 2003. "sizeof (char), sizeof (signed char) i sizeof (unsigned char) to 1, wynik sizeof zastosowany do dowolnego innego typu podstawowego (3.9.1) jest zdefiniowany przez implementację." –

2

Możesz zrobić char* pBuffer = new char[7];, a ponieważ sizeof (char) to 1 bajt, możesz go użyć jako bufora bajtowego. Pamiętaj także, aby podczas zwalniania pamięci używać delete[] (z []).

11

Inni odpowiedzieli na pytanie w formie pisemnej, ale chciałbym zasugerować trzymanie się malloc/free za takie przydziały.

new i delete służą do przydzielania obiektów. Przydzielają wymaganą pamięć i budują konstruktory/destruktory. Jeśli wiesz, że potrzebujesz tylko dowolnego bloku pamięci, użycie malloc i free jest całkowicie uzasadnione.

+1

Ale jeśli piszesz kod w C++, myślę, że lepiej jest użyć nowego/usunąć, ponieważ użyjesz go do przydzielenia obiektów. Posiadanie dwóch typów funkcji alokacji pamięci dodaje więcej zamieszania. – Naveen

+1

-1. new/delete są konstrukcjami językowymi i wprowadzają bezpieczeństwo typu bez względu na to, co przydzielasz/zwalniasz. malloc/free to artefakty pozostałe dla kompatybilności wstecznej. – sharkin

+1

@ARA, jeśli potrzebna jest dowolna ogólna blokada bajtów, nie ma żadnej korzyści z przekonania, że ​​są one w szczególności char lub unsigned char lub cokolwiek - pustka * jest bardziej szczera i wyraźna. +1 dla malloc! –

3

Tak, można.
Ale w zależności od tego, co robisz, mogą być lepsze techniki.

Czy możesz zaktualizować pytanie i powiedzieć nam, co próbujesz osiągnąć. Przy większej ilości kontekstów można zapewnić lepsze rozwiązanie.

Przykład:
Jeśli dynamicznie przydzielano bufor do odczytu z gniazda (ponieważ rozmiar nie jest znany podczas kompilacji). Alternatywą byłoby użycie wektora i dynamicznie go zmienić. Następnie można uzyskać wskaźnik do wnętrza bufora, biorąc adres pierwszego elementu.

3

Osobiście użyłbym std::vector<char>. Nie tylko otrzymujesz dowolny blok bajtów (guaranteed to be contiguous), ale dostajesz je w opakowaniu RAII.Oczywiście, nie ma potrzeby korzystania z któregokolwiek z std::vector „s metod (poza, być może, resize()), ale nie kara nie za to:

std::vector<char> buffer(7); 
void* p = &buffer[0]; 

Można użyć std::string, ale std::string oznacza„ten obiekt zawiera znaki, które mają sens podczas drukowania, "gdzie std::vector<char> oznacza" ten obiekt zawiera dowolną grupę bajtów. "