2011-10-21 9 views
5

estoy revisando una sección de C++ un código que encontré con este bloque de instrucciones:Explicación de este nuevo estado()

static void Vector3DefaultConstructor(Vector3 *self) 
{  
    new(self) Vector3();  
} 

no he llegado al otro lado del nuevo operador se utiliza de esta manera antes. ¿Alguien puede explicar por qué se llama a alguien nuevo de esta manera?

+0

Como dicen las respuestas, es una ubicación nueva. La razón * práctica * para escribir esto podría ser proporcionar una interfaz compatible con C a una biblioteca C++, aunque otros usos (como mi ejemplo std :: vector) son un poco más convencionales. – spraff

Respuesta

3

Esto se llama "ubicación new". De manera predeterminada, no asigna memoria sino que construye el objeto en la ubicación dada (aquí, self). Sin embargo, puede estar sobrecargado para una clase.

Consulte el FAQ para obtener más información.

La forma correcta de destruir un objeto construido mediante la colocación new es llamando directamente al destructor:

obj->~Vector3(); 
+0

Bueno, también podría haber una sobrecarga para 'Vector3 *' específicamente. –

+0

No es que si usa la ubicación-nueva necesitará asegurarse de que 'self-> ~ Vector3()' se llame en algún momento. Los objetos normales de C++ tienen una vida útil bien definida, cuando * necesitas * ubicación-nuevo es porque estás haciendo algo que el lenguaje no proporciona directamente. – spraff

+0

@CatPlusPlus: Buen punto, respuesta editada. – NPE

3

Puede alguien explicar por qué nueva que se llama de esta manera?

Puedo decirle lo que hace. Efectivamente llama al constructor en una pieza arbitraria de memoria, construyendo así el objeto en esa pieza de memoria. Regular new asigna memoria y construye un objeto en esa memoria; la colocación nueva solo hace la última parte.

¿Por qué alguien podría escribir ese código? Ninguna pista. Tendría más sentido si el objeto tomó un void* en lugar de un Vector3*. Pero a menos que Vector3::Vector3() sea privado, no hay razón para ocultar el nuevo uso de la ubicación dentro de una función estática como esta.

+0

NO * llama al constructor en una ** pieza de memoria ** arbitraria *. * Llama al constructor en una ** pieza ** de memoria *. – Nawaz

+0

@Nawaz Esa pieza dada es arbitraria. –

+0

@LucDanton: Hay una diferencia. [Cualquiera puede cocinar] (http: //en.wikipedia.org/wiki/Ratatouille_ (película)) no significa que Any Tom-Harry-and-Dick pueda cocinar. – Nawaz

0

Ejemplo del mundo real: std::vector asigna memoria más que suficiente para almacenar su carga actual, para reducir el costo promedio de push_back.

Si almacenó un búfer T*data, llamar a data=new T[capacity] crearía por defecto una carga de objetos T. El problema es que la semántica de vector es que solo contiene lo que has puesto en ella: podemos preasignar memoria para nuestros objetos, pero esos objetos no deberían existir aún.

La solución es hacer que el miembro vector::data sea un void* y asignarle memoria sin tipo. Ahora, siempre que agreguemos un objeto al contenedor, debemos construirlo para que este objeto exista y darle sentido al puntero sin procesar.

template <typename T> 
void vector <T> :: push_back (const T & value) 
{ 
    resize (m_size + 1); 
    // construct a new T in the void buffer. 
    new (reinterpret_cast <T*> (m_data) + m_size) T (value); 
    ++ m_size; 
} 

template <typeame T> 
void vector <T> :: pop_back() 
{ 
    (reinterpret_cast <T*> (m_data) + m_size) -> ~ T(); 
    -- size; 
}