sirven que punteros puntero para operaciones los declaracion con cadenas aritmetica c++ memory pointers initialization

que - punteros c++



¿Por qué los punteros no se inicializan con NULL de manera predeterminada? (15)

¿Puede alguien explicar por qué los punteros no se inicializan en NULL ?
Ejemplo:

void test(){ char *buf; if (!buf) // whatever }

El programa no entraría en el if porque buf no es nulo.

Me gustaría saber por qué, en qué caso necesitamos una variable con basura encendida, especialmente los indicadores que abordan la basura en la memoria.


¿De qué son estos indicadores de los que hablas?

Para seguridad de excepción, siempre use auto_ptr , shared_ptr , weak_ptr y sus otras variantes.
Un sello de buen código es uno que no incluye una sola llamada para delete .


Además, tenemos una advertencia para cuando lo explotes: "posiblemente se use antes de asignarle un valor" o verbage similar según tu compilador.

Compilas con advertencias, ¿verdad?


Bueno, si C ++ inicializó punteros, entonces la gente de C quejándose de que "C ++ es más lento que C" tendría algo real para aferrarse;)


C ++ proviene de un fondo C, y hay algunas razones que vuelven de esto:

C, incluso más que C ++ es un reemplazo de lenguaje ensamblador. No hace nada que no le digas que haga. Por lo tanto: si quiere NULL, ¡hazlo!

Además, si anula las cosas en un lenguaje básico como C, las preguntas de coherencia automática aparecen: si malloc algo, ¿debería ponerse a cero automáticamente? ¿Qué pasa con una estructura creada en la pila? ¿Deberían todos los bytes estar en cero? ¿Qué pasa con las variables globales? ¿Qué tal una declaración como "(* 0x18)"? ¿Eso no significa que la posición de memoria 0x18 debe ponerse a cero?


Citando a Bjarne Stroustrup en TC ++ PL (edición especial p.22):

La implementación de una característica no debe imponer gastos generales significativos en los programas que no lo requieren.


Hay pocas situaciones en las que alguna vez tenga sentido que una variable no se inicialice, y la inicialización por defecto tiene un costo bajo, entonces, ¿por qué hacerlo?

C ++ no es C89. Demonios, incluso C no es C89. Puede mezclar declaraciones y códigos, por lo que debe diferir la declaración hasta el momento en que tenga un valor adecuado para inicializar.


Oh chico. La respuesta real es que es fácil poner a cero la memoria, que es la inicialización básica para, por ejemplo, un puntero. Lo cual tampoco tiene nada que ver con la inicialización del objeto en sí.

Teniendo en cuenta las advertencias que la mayoría de los compiladores dan en los niveles más altos, no puedo imaginar la programación al más alto nivel y tratarlos como errores. Desde que usarlos nunca me ha salvado ni siquiera un error en grandes cantidades de código producido, no puedo recomendarlo.


Otra posible razón por la cual, es que a los punteros de tiempo de enlace se les da una dirección, pero el direccionamiento / desreferenciación indirecta de un puntero es responsabilidad del programador. Por lo general, al compilador no le importa, pero la carga se transfiere al programador para administrar los indicadores y asegurarse de que no haya pérdidas de memoria.

Realmente, en pocas palabras, se inicializan en el sentido de que en el tiempo de enlace la variable de puntero recibe una dirección. En su código de ejemplo anterior, está garantizado que se bloqueará o generará un SIGSEGV.

En aras de la cordura, siempre inicialice los punteros a NULL, de esa forma si cualquier intento de desreferenciarlo sin malloc o new indicará al programador el motivo por el cual el programa se comportó mal.

Espero que esto ayude y tenga sentido. Saludos, Tom.


Por razones históricas, principalmente porque así es como se hace en C. Por qué se hace así en C, es otra cuestión, pero creo que el principio de cero carga estuvo involucrado de alguna manera en esta decisión de diseño.


Porque la inicialización lleva tiempo. Y en C ++, lo primero que debe hacer con cualquier variable es inicializarla explícitamente:

int * p = & some_int;

o:

int * p = 0;

o:

class A { public: A() : p( 0 ) {} // initialise via constructor private: int * p; };


Porque uno de los pilares de C ++ es:

No pagas por lo que no necesitas

Por esta misma razón, el operator[] de la clase vector no verifica si el índice está fuera de límites, por ejemplo.


Si desea que un puntero siempre se inicialice en NULL, puede usar una plantilla de C ++ para emular esa funcionalidad:

template<typename T> class InitializedPointer { public: typedef T TObj; typedef TObj *PObj; protected: PObj m_pPointer; public: // Constructors / Destructor inline InitializedPointer() { m_pPointer=0; } inline InitializedPointer(PObj InPointer) { m_pPointer = InPointer; } inline InitializedPointer(const InitializedPointer& oCopy) { m_pPointer = oCopy.m_pPointer; } inline ~InitializedPointer() { m_pPointer=0; } inline PObj GetPointer() const { return (m_pPointer); } inline void SetPointer(PObj InPtr) { m_pPointer = InPtr; } // Operator Overloads inline InitializedPointer& operator = (PObj InPtr) { SetPointer(InPtr); return(*this); } inline InitializedPointer& operator = (const InitializedPointer& InPtr) { SetPointer(InPtr.m_pPointer); return(*this); } inline PObj operator ->() const { return (m_pPointer); } inline TObj &operator *() const { return (*m_pPointer); } inline bool operator!=(PObj pOther) const { return(m_pPointer!=pOther); } inline bool operator==(PObj pOther) const { return(m_pPointer==pOther); } inline bool operator!=(const InitializedPointer& InPtr) const { return(m_pPointer!=InPtr.m_pPointer); } inline bool operator==(const InitializedPointer& InPtr) const { return(m_pPointer==InPtr.m_pPointer); } inline bool operator<=(PObj pOther) const { return(m_pPointer<=pOther); } inline bool operator>=(PObj pOther) const { return(m_pPointer>=pOther); } inline bool operator<=(const InitializedPointer& InPtr) const { return(m_pPointer<=InPtr.m_pPointer); } inline bool operator>=(const InitializedPointer& InPtr) const { return(m_pPointer>=InPtr.m_pPointer); } inline bool operator<(PObj pOther) const { return(m_pPointer<pOther); } inline bool operator>(PObj pOther) const { return(m_pPointer>pOther); } inline bool operator<(const InitializedPointer& InPtr) const { return(m_pPointer<InPtr.m_pPointer); } inline bool operator>(const InitializedPointer& InPtr) const { return(m_pPointer>InPtr.m_pPointer); } };


Tenga en cuenta que los datos estáticos se inicializan a 0 (a menos que indique lo contrario).

Y sí, siempre debe declarar sus variables lo más tarde posible y con un valor inicial. Código como

int j; char *foo;

debe hacer sonar las alarmas cuando lo lea. No sé si se puede persuadir a cualquier lint para que se preocupe, ya que es 100% legal.


Todos nos damos cuenta de que el puntero (y otros tipos de POD) deben inicializarse.
La pregunta entonces se convierte en ''quién debería inicializarlos''.

Bueno, básicamente hay dos métodos:

  • El compilador los inicializa.
  • El desarrollador los inicializa.

Supongamos que el compilador inicializó cualquier variable no inicializada explícitamente por el desarrollador. Luego nos encontramos con situaciones en las que la inicialización de la variable no era trivial y la razón por la que el desarrollador no lo hizo en el punto de declaración era que él / ella necesitaba realizar alguna operación y luego asignarla.

Entonces ahora tenemos la situación de que el compilador ha agregado una instrucción adicional al código que inicializa la variable a NULL, luego se agrega el código de desarrollador para realizar la inicialización correcta. O en otras condiciones, la variable posiblemente nunca se use. Muchos desarrolladores de C ++ gritarían falta en ambas condiciones a costa de esa instrucción adicional.

No es solo por el tiempo. Pero también espacio Hay muchos entornos en los que ambos recursos son una prioridad y los desarrolladores tampoco quieren renunciar.

PERO : Puede simular el efecto de forzar la inicialización. La mayoría de los compiladores le advertirán sobre las variables no inicializadas. Así que siempre cambio mi nivel de advertencia al nivel más alto posible. Luego dígale al compilador que trate todas las advertencias como errores. Bajo estas condiciones, la mayoría de los compiladores generarán un error para las variables que no se inicializaron pero que se usaron y, por lo tanto, evitarán que se genere el código.


Un puntero es solo otro tipo. Si crea un int , char o cualquier otro tipo de POD, no se inicializa a cero, entonces ¿por qué debería un puntero? Esto podría considerarse una sobrecarga innecesaria para alguien que escribe un programa como este.

char* pBuf; if (condition) { pBuf = new char[50]; } else { pBuf = m_myMember->buf(); }

Si sabe que va a inicializarlo, ¿por qué el programa debe incurrir en un costo cuando crea pBuf en la parte superior del método? Este es el principio de cero sobrecarga.