2010-03-23 11 views
7

Mój program C++ potrzebuje bloku niezainicjowanej pamięci i wskaźnika void* do tego bloku, aby można go było przekazać do biblioteki innej firmy. Chcę przejąć kontrolę nad czasem życia bloku do biblioteki, więc nie chcę używać std::vector. Kiedy biblioteka zostanie wykonana z blokiem, wywoła wywołanie zwrotne, które muszę dostarczyć, i które zwolni blok. W C użyłbym malloc(), a później free().Którego użyć - "operator nowy" lub "operator nowy []" - aby przydzielić blok surowej pamięci w C++?

W C++ można też nazwać ::operator new lub ::operator new[] i ::operator delete lub operator delete[] odpowiednio później:

void* newBlock = ::operator new(sizeOfBlock); 
// then, later 
::operator delete(newBlock); 

Wygląda zarówno ::operator new i ::operator new[] mają dokładnie taką samą sygnaturę i dokładnie takie samo zachowanie. To samo dotyczy ::operator delete i ::operator delete[]. Jedyne, czego nie powinienem robić, to parowanie operator new z i na odwrót - niezdefiniowane zachowanie. Poza tą parą, którą wybieram i dlaczego?

+5

Zakładam, że wiesz, że powinieneś użyć 'std :: vector ', yadda yadda. – GManNickG

+0

Dlaczego myślisz, że przy std :: vector nie masz kontroli nad czasem życia obiektu? –

+0

Pytanie jest niejasne. Czy masz kontrolę nad dealokacją, czy przekazujesz tę odpowiedzialność do biblioteki? Wszystkie odpowiedzi sprzed edycji nie uwzględniają zmodyfikowanych wymagań. –

Odpowiedz

7

Zastosowanie new z jednego przedmiotu i new[] z tablicą obiektów. Tak więc, na przykład:

 
int* x = new int; // Allocates single int 
int* y = new int[5]; // Allocates an array of integers 

*x = 10; // Assignment to single value 
y[0] = 8; // Assignment to element of the array 

Jeśli wszystko co robisz jest przydzielenie bufor pamięci, a następnie przydzielić tablicę char jak w:

 
int bufferlen = /* choose a buffer size somehow */ 
char* buffer = new char[bufferlen]; 
// now can refer to buffer[0] ... buffer[bufferlen-1] 

Jednak w C++, należy naprawdę korzystać std::vector dla dowolne tablice i powinieneś użyć std::string dla tablic znaków, które mają być interpretowane lub używane jako łańcuchy znaków.

Nie ma powodu, aby wywoływać w sposób wyraźny wartości ::operator new lub ::operator new[], zamiast używać zwykłej składni tych wywołań. W przypadku POD i typów pierwotnych (np. char) inicjalizacja nie będzie miała miejsca. Jeśli potrzebujesz bufora void*, po prostu użyj static_cast, aby przekonwertować char* na void*.

+2

OP nie mówi o 'new int' i' new int [5] ', ale w szczególności wywołuje funkcje o podanych nazwach, np. 'void * p = operator new (50);' vs 'void * p = operator new [] (50);'. –

+0

@Roger, dzięki. Nie było to jasne aż do późniejszej edycji. –

+2

Twoja aktualizacja jest nieco błędna. Istnieje różnica między 'new int' i' new int() '(ten ostatni obiekt jest gwarantowany do zainicjowania na zero) i podobnie dla każdego typu POD. Jeden specjalny przypadek działa również dla nowego []: 'new int [5]()'. –

0

dla przydzielania pamięci na tablicy/listy użyć new [] inne niż wykorzystujące nowe ...

1

Zaletą C++ new operatorów ponad C na malloc() i free() jest to, że były zgłasza wyjątek, jeśli nie ma wystarczającej ilości pamięci, zamiast wracać NULL.

Jeśli chodzi o wybór nowego (rozmiaru) i nowego [] dla buforów znaków, byłbym zwolennikiem tego drugiego, ponieważ mniej prawdopodobne jest zaskoczenie osób utrzymujących kod później, tj. char* buf = new char[size] i delete[] buf.

Wartości w buforze nie zostaną zainicjowane i nie ma sprawdzania zasięgu - musisz zbudować ładny obiekt C++, aby zrobić to za Ciebie, lub użyć istniejącego obiektu, takiego jak std::vector lub std::string.

1

Na to pytanie nie można odpowiedzieć w sposób rozsądny.

Po pierwsze, mówi się, że program "potrzebuje" bloku niezainicjowanej pamięci, ale z podanego przykładowego kodu wydaje się, że program "potrzebuje" bloku pamięci niezainicjowanej i UNTYPED, która wydaje się nie być bardzo C++ lub OO .

Po drugie, std :: vector zapewnia wyłączną i automatyczną kontrolę nad blokiem wpisanej pamięci, która może lub może nie zmieniać się w zależności od jego użycia. Tę kontrolę można utracić, jeśli instancja std :: vector zostanie utworzona na stercie i będzie śledzona za pomocą surowych wskaźników, tak jak w przypadku dowolnego innego obiektu C lub C++, takiego jak blok pustki *.

Po trzecie, jakie jest zamierzone użycie tego bloku pamięci? Odpowiedź na to pytanie może, ale nie musi, dyktować użycie operatora new lub operatora new []. Czy w projekcie tego programu istnieje jedna interpretacja tego bloku pamięci? Jakie semantyki własności potrzebujesz, jeśli takie są? Itd., Itp.

+0

Uwaga: na te pytania odpowiedziano w późniejszej edycji. –