2009-01-23 10 views

Respuesta

23

Asignar en la pila, o bien declarar su objeto como una variable local por valor, o en realidad se puede utilizar alloca para obtener un puntero y luego utilizar el nuevo operador en el lugar:

void *p = alloca(sizeof(Whatever)); 
new (p) Whatever(constructorArguments); 

Sin embargo, si utiliza alloca y in-place new garantiza que la memoria se libera al volver, usted renuncia a las llamadas de destrucción automática. Si solo está tratando de asegurarse de que la memoria se libera al salir del alcance, considere usar std::auto_ptr<T> o algún otro tipo de puntero inteligente.

12

Jeffrey Hantin tiene bastante razón de que puede usar la colocación nueva para crearla en la pila con alloca. Pero, en serio, ¿por qué? En su lugar, solo haga lo siguiente:

class C { /* ... */ }; 

void func() { 
    C var; 
    C *ptr = &var; 

    // do whatever with ptr 
} 

Ahora tiene un puntero a un objeto asignado en la pila. Y, se destruirá adecuadamente cuando exista tu función.

+2

Su ejemplo es exactamente lo que quise decir al declararlo como una variable local por valor. –

+0

Nota: la clase debe tener un constructor vacío definido en cpp, si ya tiene un constructor no vacío definido. – kevinf

+0

caso de uso que tengo - digamos 'C' tiene un método' virtual' anulado en las subclases 'C1' y' C2'. Entonces es posible que desee hacer 'C * ptr = criterios? nuevo (alloca (sizeof (C1))) C1 (...): nuevo (alloca (sizeof (C2))) C2 (...); ' – rampion

5

Se podría hacer:

Whatever* aWhatever = new (alloca(sizeof(Whatever))) Whatever; 

Usted podría utiliza una clase RAII hacer la destrucción supongo (EDIT: También ver this other answer for more information on potential problems with this approach):

template <class TYPE> 
class RAII 
    { 
    public: 
     explicit RAII(TYPE* p) : ptr(p) {} 
     ~RAII() { ptr->~TYPE(); } 
     TYPE& operator*() const { return *ptr; } 
    private: 
     TYPE* ptr; 
    } 

void example() 
    { 
    RAII<Whatever> ptr = new (alloca(sizeof(Whatever))) Whatever; 
    } 

se puede utilizar una macro para ocultar la alloca.

Saludos DaveF

2

Tenga cuidado al usar _alloca() con GCC

GCC tiene una bug which makes _alloca() incompatible with SJLJ exception handling en C++ (Dwarf2 se ha informado que funcionan correctamente). Cuando se descarta una excepción de la función que asigna la memoria, el error causa daños en la pila antes de que se ejecuten los destructores. Esto significa que cualquier clase RAII que trabaje en el (los) objeto (s) asignado (s) tiene que ejecutar en otra función para que funcione correctamente. La forma correcta de hacerlo es así:

void AllocateAndDoSomething() 
{ 
    Foo* pFoo = reinterpret_cast<Foo*>(_alloca(sizeof(Foo))); 
    new (pFoo) Foo; 

    // WARNING: This will not work correctly! 
    // ScopedDestructor autoDestroy(pFoo); 
    // pFoo->DoSomething(); 

    // Instead, do like this: 
    DoSomething(pFoo); 
} 

void DoSomething(Foo* pFoo) 
{ 
    // Here, destruction will take place in a different call frame, where problems 
    // with _alloca() automatic management do not occur. 
    ScopedDestructor autoDestroy(pFoo); 
    pFoo->DoSomething(); 
} 
Cuestiones relacionadas