2010-04-28 22 views
12

pregunta tonta, pero cada vez que llamas nueva, ¿siempre tienes un puntero?el operador "nuevo" en C++, pregunta del puntero

SomeClass *person = new SomeClass(); 

Y es que debido a que necesita un puntero para señalar a ese nuevo espacio de memoria que se asignó para la persona variables SomeClass? ¡Gracias!

+1

Véase también http://stackoverflow.com/questions/2697892/. – sbi

Respuesta

15

Si new finaliza correctamente, siempre devuelve un puntero (si no se completa correctamente, se produce una excepción y no se devuelve nada).

El puntero es al objeto que se creó, o en el caso de una matriz, un puntero al primer elemento de la matriz.

+1

Uno puede hacer 'MyClass * p = new (std :: nothrow) MyClass'. Aquí, en caso de falla, se devuelve [puntero nulo] (http://www.cplusplus.com/reference/new/operator%20new/) en lugar de arrojar. –

0

La nueva expresión devuelve un puntero, pero puede usarlo con las clases "puntero inteligente" (por ejemplo, from Boost). Por lo tanto:

 
boost::shared_ptr<SomePerson> person(new SomePerson); 

También debo señalar que, a pesar de que se puede utilizar para el uso de los paréntesis, si viene de un fondo de Java, en C++, los paréntesis no son necesarios cuando se utiliza el constructor predeterminado. Entonces, por ejemplo, uno normalmente escribe new T cuando se construye por defecto, pero uno escribe new T(param), o new T(param1,...,paramN) al construir un objeto usando un constructor que no sea el predeterminado.

Sí, eso es correcto; uno podría, teóricamente, escribir (nuevo SomePerson) -> doSomething(), pero eso sería una pérdida de memoria; C++ no tiene recolección de basura, por lo que es necesario almacenar el resultado de la nueva expresión en algo (un puntero o un puntero inteligente) para poder desasignarlo adecuadamente.

+3

Tenga en cuenta que 'new T' y' new T() 'tienen resultados diferentes para tipos POD y tipos de clase sin constructores declarados por el usuario:' new T() 'valorizará la inicialización del objeto, mientras que' new T' no lo hará. –

+0

@James, sí, soy consciente de eso; Sin embargo, SomePerson es probablemente una clase. –

+0

Si los parientes vacíos importan en una expresión 'nueva' es una de las pequeñas pesadillas de C++: http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-name-make-a- difference-with-new/620402 # 620402 –

3

Sí, siempre un puntero. Incluso si desea sobrecargar nuevo, el tipo de devolución debe ser void *.
Y tiene razón sobre el propósito

1

Sí. Si pregunta por qué no devuelve una referencia, ya que las referencias son más bonitas que las indicadoras, la respuesta es patrimonio histórico.

Cuando C++ estaba en desarrollo, si la máquina no podía obtener memoria para el objeto, se devolvía un puntero especial NULL. Esto es lo que se hace en C:

SomeClass *person; 
person = (SomeClass*) malloc(sizeof(SomeClass)); 
if (person == NULL) fprintf(stderr, "no more people allowed!"); 

En C++ estándar, los errores son devueltos por excepción en su lugar:

try { 
    SomeClass *person = new SomeClass; 
    // do something 
} catch (std::bad_alloc) { 
    std::cerr << "no more people!" << std::endl; 
} catch (...) { 
    // using exceptions allows for other errors 
    // from inside SomeClass::SomeClass too 
} 

Todavía puede hacerlo de la manera antigua, sin embargo, con nothrow:

SomeClass *person = new(std::nothrow) SomeClass; 
if (person == NULL) std::cerr << "no more people allowed!" << std::endl; 

El resultado es, esto es perfectamente razonable y un buen estilo:

SomeClass &person = * new SomeClass; // don't need no stinkin pointers! 
+4

** SomeClass & person = * new SomeClass; ** - No creo que sea un buen estilo, porque lo usas como una variable automática y aún debes recordar eliminarlo al final de alcance Camino directo a mem-leaks, IMO. Y una gran sorpresa para alguien que mantendrá su código –

+1

Creo que la mayoría consideraría el último ejemplo de mal estilo. Aunque puede recuperar el puntero en algún punto, se vuelve menos claro que el objeto se asigna dinámicamente y debe eliminarse. También debe preocuparse por el día en que alguien reemplaza el tipo de referencia con una clase base en una situación de herencia múltiple; entonces, es posible que no pueda recuperar el puntero asignado. –

+0

@Alexander, @Nick: usar 'new' si el objeto no va a algún lado fuera del alcance local es ** bad design **, y ninguna cantidad de estilo puede compensarlo. – Potatoswatter

2

nuevo crea un objeto en el montón y todo lo que puede devolver es su dirección: un puntero.