2010-03-23 13 views
7

Mi programa C++ necesita un bloque de memoria no inicializada y un puntero void* a ese bloque para que pueda entregarlo a una biblioteca de terceros. Quiero pasar el control de la vida útil del bloque a la biblioteca, por lo que no quiero usar std::vector. Cuando la biblioteca termine con el bloque, se llamará a una devolución de llamada que tengo que suministrar y eso desasignará el bloque. En C usaría malloc() y más tarde free().¿Qué usar - "operador nuevo" u "operador nuevo []" - para asignar un bloque de memoria sin procesar en C++?

En C++ puedo llamar ya sea ::operator new o ::operator new[] y ::operator delete o operator delete[] respectivamente después:

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

Parece que tanto ::operator new y ::operator new[] tienen exactamente la misma firma y exactamente el mismo comportamiento. Lo mismo para ::operator delete y ::operator delete[]. Lo único que no debería hacer es vincular operator new con operator delete[] y viceversa - comportamiento indefinido. ¿Aparte de qué par elegir y por qué?

+5

Supongo que usted sabe que debe usar 'std :: vector ', yadda yadda. – GManNickG

+0

¿Por qué crees que con std :: vector no tienes control sobre la vida útil del objeto? –

+0

La pregunta no está clara. ¿Tiene control sobre la desasignación o transfiere esa responsabilidad a una biblioteca? Todas las respuestas anteriores a esa edición no abordan los requisitos modificados. –

Respuesta

7

Uso new con un solo objeto y new[] con una serie de objetos. Así, por ejemplo:

 
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 

Si todo lo que está haciendo es la asignación de un búfer de memoria, a continuación, asignar una matriz de char como en:

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

Sin embargo, en C++, que realmente debería usar std::vector de matrices arbitrarias, y debe usar std::string para matrices de caracteres que deben interpretarse o utilizarse como cadenas.

No hay ninguna razón para invocar ::operator new o ::operator new[] explícitamente en lugar de utilizar la sintaxis habitual para estas llamadas. Para POD y tipos primitivos (por ejemplo, char) no tendrá lugar ninguna inicialización. Si necesita obtener un buffer void*, simplemente use static_cast para convertir char* en void*.

+2

El OP no está hablando de 'new int' y' new int [5] ', sino que específicamente llama a las funciones con los nombres dados, p. 'void * p = operator new (50);' versus 'void * p = operator new [] (50);'. –

+0

@Roger, gracias. Esto no fue aclarado hasta una edición posterior. –

+2

Su actualización es un poco incorrecta. Hay una diferencia entre 'new int' y' new int() '(el último objeto está garantizado para ser inicializado a cero), y de manera similar para cualquier tipo de POD. Un caso especial también funciona para new []: 'new int [5]()'. –

0

para la asignación de memoria a la matriz/lista de cuenta nuevos [] distinta de la cuenta nuevos ...

1

La ventaja de los operadores de C++ new más de C de malloc() y free() es que el primero se produce una excepción si no hay suficiente memoria, en lugar de volver NULL.

En cuanto a elegir nuevo (tamaño) y nuevo [] para búferes de caracteres, recomendaría este último ya que es menos probable que sorprenda a las personas que mantienen el código más tarde, es decir, char* buf = new char[size] y delete[] buf.

Los valores en el búfer no se inicializarán, y no hay comprobación de rango: tiene que crear un buen objeto de C++ para hacer eso por usted o utilizar un objeto existente como std::vector o std::string.

1

La pregunta no puede responderse con sensatez.

En primer lugar, se dice que el programa 'necesita' un bloque de memoria no inicializada pero, a partir del ejemplo de código dado, parece que el programa 'necesita' un bloque de memoria no unificada y UNTYPED que parece no ser muy C++ u OO .

En segundo lugar, un estándar :: vector da control único y automático sobre un bloque de memoria tipada que puede o no cambiar de tamaño según su uso. Puede perder este control si se crea una instancia de std :: vector en el montón y se rastrea con punteros sin procesar al igual que para cualquier otro objeto C o C++, como un bloque de memoria void *.

En tercer lugar, ¿cuál es el uso previsto de este bloque de memoria? La respuesta a esto puede o no dictar el uso de operador nuevo u operador nuevo []. En el diseño de este programa, ¿hay una interpretación única de este bloque de memoria? ¿Qué semántica de propiedad necesitas, si hay alguna? Etc, etc.

+0

Nota: Estas preguntas fueron respondidas en una edición posterior. –

Cuestiones relacionadas