ejemplos descargar definicion compiler caracteristicas c++

descargar - ¿Cuáles son los conceptos a menudo incomprendidos en C++?



c++ manual (30)

Alineación de memoria.

¿Cuáles son los conceptos a menudo incomprendidos en c ++?


Aquí hay un concepto importante en C ++ que a menudo se olvida:

C ++ no debe usarse simplemente como un lenguaje orientado a objetos como Java o C #. Inspírate del STL y escribe un código genérico.


C ++ es un lenguaje multi-paradigma. Muchas personas asocian C ++ estrictamente con OOP.


C ++ no es C con cadena y vector!


El concepto más pernicioso que he visto es que debería tratarse como C con algunos complementos. De hecho, con los sistemas modernos de C ++, debería tratarse como un idioma diferente, y la mayoría de los ataques de C ++ que veo se basan en el modelo "C con complementos".

Para mencionar algunos problemas:

Si bien es probable que necesite saber la diferencia entre delete y delete[] , normalmente no debería escribir ninguno. Utilice los punteros inteligentes y std::vector<> .

De hecho, debe usar un * solo en raras ocasiones. Use std :: string para cadenas. (Sí, está mal diseñado. Úselo de todos modos).

RAII significa que generalmente no tiene que escribir el código de limpieza. El código de limpieza es de mal estilo y destruye la localidad conceptual. Como beneficio adicional, el uso de RAII (incluidos los indicadores inteligentes) le ofrece una gran cantidad de excepciones básicas de seguridad de forma gratuita. En general, es mucho mejor que la recolección de basura de alguna manera.

En general, los miembros de la clase de datos no deben ser directamente visibles, ya sea por ser public o por tener getters y setters. Hay excepciones (como xey en una clase de puntos), pero son excepciones y deben considerarse como tales.

Y el grande: no existe un lenguaje como C / C ++. Es posible escribir programas que se puedan compilar correctamente en cualquier idioma, pero tales programas no son buenos en C ++ y normalmente no son buenos C. Los idiomas han sido divergentes desde que Stroustrup comenzó a trabajar en "C con clases", y ahora son menos similares que nunca. El uso de "C / C ++" como nombre de idioma es evidencia prima facie de que el usuario no sabe de lo que está hablando. C ++, utilizado correctamente, no se parece más a C que Java o C #.


El uso excesivo de la herencia no está relacionado con el polimorfismo. La mayoría de las veces, a menos que realmente use polimorfismo en tiempo de ejecución, la composición o el polimorfismo estático (es decir, plantillas) es mejor.


En orden decreciente:

  1. asegúrese de lanzar punteros para la memoria asignada
  2. cuando los destructores deberían ser virtuales
  3. cómo funcionan las funciones virtuales

Curiosamente, no muchas personas conocen todos los detalles de las funciones virtuales, pero aún parecen estar de acuerdo con el trabajo realizado.


La diferencia entre asignación e inicialización:

string s = "foo"; // initialisation s = "bar"; // assignment

La inicialización siempre usa constructores, la asignación siempre usa operator =


La palabra clave estática que puede significar una de tres cosas distintas según dónde se use.

  1. Puede ser una función miembro estática o una variable miembro.
  2. Puede ser una variable estática o una función declarada en el ámbito del espacio de nombres.
  3. Puede ser una variable estática declarada dentro de una función.

C ++ no es C con clases!

Y no hay un lenguaje llamado C / C ++. Todo va cuesta abajo desde allí.


Las matrices no son punteros

Ellos son diferentes. Entonces, &array no es un puntero a un puntero, sino un puntero a una matriz. Este es el concepto más incomprendido tanto en C como en C ++ en mi opinión. ¡Tienes que visitar todas las respuestas de SO que dicen pasar las matrices de 2 d como type** !


  • Punteros a miembros y punteros a funciones de miembros.
  • Parámetros de plantilla sin tipo.
  • Herencia múltiple, particularmente clases base virtuales y objetos base compartidos.
  • Orden de construcción y destrucción, el estado de las funciones virtuales en el medio de la construcción de una clase base intermedia.
  • Seguridad del molde y tamaños variables. No, no puede suponer que sizeof(void *) == sizeof(int) (o cualquier otro tipo para el caso, a menos que un encabezado portátil lo garantice específicamente) en un código portátil.
  • Aritmética del puntero.

  • Que los espacios de nombres anónimos son casi siempre lo que realmente se desea cuando las personas están creando variables estáticas en C ++
  • Al crear archivos de encabezado de biblioteca, el idioma pimpl ( http://www.gotw.ca/gotw/024.htm ) debe usarse para casi todas las funciones y miembros privados para ayudar en la administración de dependencias.

Aquí están algunas:

  1. Usar plantillas para implementar polimorfismo sin tablas, a la ATL.
  2. const -ness lógico vs const -ness real en la memoria. Cuándo usar la palabra clave mutable .

AGRADECIMIENTO: Gracias por corregir mi error, Spoulson.

EDITAR:

Aquí hay más:

  1. Herencia virtual (no métodos virtuales): ¡De hecho, no lo entiendo en absoluto! (con eso, quiero decir, no sé cómo se implementa)
  2. Uniones cuyos miembros son objetos cuyas clases respectivas tienen constructores no triviales.

C ++ no es un lenguaje típico orientado a objetos.

No me creas? mira el STL, más plantillas que objetos.

Es casi imposible usar formas Java / C # de escribir código orientado a objetos; simplemente no funciona.

  • En la programación de Java / C #, hay muchas aplicaciones new , muchos objetos de utilidad que implementan una funcionalidad cohesiva única.
  • En C ++, cualquier objeto new ed debe eliminarse, pero siempre existe el problema de a quién pertenece el objeto
  • Como resultado, los objetos tienden a crearse en la pila
  • Pero cuando haces eso, tienes que copiarlos todo el tiempo si vas a pasarlos a otras funciones / objetos, desperdiciando mucho rendimiento que se dice que se logra con el entorno no administrado de C ++.
  • Al darse cuenta de eso, debes pensar en otras formas de organizar tu código
  • Es posible que termine haciendo las cosas de manera procedimental, o utilizando modismos de metaprogramación como punteros inteligentes
  • En este punto, se ha dado cuenta de que OO en C ++ no se puede usar de la misma manera que en Java / C #

QED

Si insiste en hacer oop con punteros, generalmente tendrá clases grandes (¡gigantescas!), Con relaciones de propiedad claramente definidas entre los objetos para evitar pérdidas de memoria. Y luego, incluso si haces eso, ya estás demasiado lejos del idioma Java / C # de oop.

En realidad, inventé el término "orientado a objetos", y puedo decir que no tenía C ++ en mente.
- Alan Kay ( haz clic en el enlace, es un video, la cita es a las 10:33)

Aunque desde un punto de vista purista (por ejemplo, Alan Kay), incluso Java y C # no llegan a ser verdad


Hay algunas cosas que las personas parecen estar constantemente confundidas o que no tienen idea acerca de:

  1. Punteros, especialmente punteros de función y punteros múltiples (por ejemplo, int (*) (void *), void ***)

  2. La palabra clave const y const correctness (por ejemplo, ¿cuál es la diferencia entre const char *, char * const y const char * const, y qué hace void class :: member () const; mean?)

  3. La asignación de memoria (por ejemplo, cada puntero new''ed debe eliminarse, malloc / free no debe mezclarse con new / delete, cuándo utilizar delete [] en lugar de delete, por qué las funciones C siguen siendo útiles (por ejemplo, expand (), realloc ( )))

  4. Ámbito de aplicación (es decir, que puede usar {} por sí solo para crear un nuevo ámbito para nombres de variables, en lugar de solo como parte de if, para etc ...)

  5. Cambiar declaraciones (por ejemplo, no entendiendo que pueden optimizar también (o mejor en algunos casos) que las cadenas de ifs, que no se comprende el entendimiento y sus aplicaciones prácticas (loop labrándose como ejemplo) o que hay un caso predeterminado)

  6. Convenciones de llamada (por ejemplo, ¿cuál es la diferencia entre cdecl y stdcall, cómo implementarías una función pascal, por qué incluso importa?)

  7. Herencia y herencia múltiple y, más generalmente, todo el paradigma OO.

  8. El ensamblador en línea, como generalmente se implementa, no es parte de C ++.


Punteros.

Desreferenciando los punteros. Por cualquiera de los dos . o ->

Dirección de uso de & para cuando se requiere un puntero.

Funciones que toman params por referencia especificando a & en la firma.

Puntero a punteros a punteros *** o punteros por referencia void someFunc(int *& arg)


std::vector no crea elementos cuando se usa reserva

Lo he visto que los programadores argumentan que pueden acceder a los miembros en posiciones mayores de lo que size() devuelve si reserve() hasta esas posiciones. Esa es una suposición errónea, pero es muy común entre los programadores, especialmente porque es bastante difícil para el compilador diagnosticar un error, que silenciosamente hará que las cosas "funcionen".


C estructura VS C ++ estructura a menudo se entiende mal.


Encabezados y archivos de implementación

Este es también un concepto incomprendido por muchos. Preguntas como qué se incluye en los archivos de cabecera y por qué causa errores de enlace si las definiciones de funciones aparecen varias veces en un programa por un lado, pero no cuando las definiciones de clase aparecen varias veces en el otro lado.

Muy similar a esas preguntas es por qué es importante tener protectores de cabecera .


Un puntero es un iterador, pero un iterador no siempre es un puntero

Este es también un concepto a menudo malentendido. Un puntero a un objeto es un iterador de acceso aleatorio: puede incrementarse / decrementarse mediante una cantidad arbitraria de elementos y puede leerse y escribirse. Sin embargo, una clase de iterador que tiene sobrecargas de operadores que cumplen esos requisitos también. Por lo tanto, también es un iterador pero, por supuesto, no es un puntero.

Recuerdo que uno de mis antiguos profesores de C ++ estaba enseñando (erróneamente) que si obtenías un puntero a un elemento de un vector vec.begin(). En realidad estaba asumiendo, sin saberlo, que el vector implementa sus iteradores usando punteros.


Que C ++ tiene administración automática de recursos.

(La mayoría de las personas que afirman que C ++ no tiene administración de memoria intenta usar nuevas y eliminar demasiado, sin darse cuenta de que si permitieran que C ++ administre el recurso por sí mismo, la tarea se vuelve mucho más fácil).

Ejemplo: (Hecho con una API inventada porque no tengo tiempo para verificar los documentos ahora)

// C++ void DoSomething() { File file("/tmp/dosomething", "rb"); ... do stuff with file... // file is automatically free''ed and closed. } // C# public void DoSomething() { File file = new File("/tmp/dosomething", "rb"); ... do stuff with file... // file is NOT automatically closed. // What if the caller calls DoSomething() in a tight loop? // C# requires you to be aware of the implementation of the File class // and forces you to accommodate, thus voiding implementation-hiding // principles. // Approaches may include: // 1) Utilizing the IDisposable pattern. // 2) Utilizing try-finally guards, which quickly gets messy. // 3) The nagging doubt that you''ve forgotten something /somewhere/ in your // 1 million loc project. // 4) The realization that point #3 can not be fixed by fixing the File // class. }


Todavía no entiendo por qué el vector no tiene pop_front y el hecho de que no puedo ordenar (list.begin (), list.end ()) ..


Creo que el concepto más incomprendido sobre C ++ es por qué existe y cuál es su propósito. A menudo está bajo fuego desde arriba (Java, C # etc.) y desde abajo (C). C ++ tiene la capacidad de operar cerca de la máquina para manejar la complejidad computacional y los mecanismos de abstracción para administrar la complejidad del dominio.


NULL siempre es cero.

Muchos confunden NULL con una dirección, y piensan que no es necesariamente cero si la plataforma tiene una dirección de puntero nulo diferente.

Pero NULL siempre es cero y no es una dirección. Es una expresión entera constante cero que se puede convertir a tipos de puntero.


Las funciones gratuitas no son malas solo porque no están dentro de una clase. C ++ no es solo un lenguaje OOP, sino que se basa en una gran cantidad de técnicas.

Lo he escuchado muchas veces cuando las personas dicen que las funciones gratuitas (aquellas en los espacios de nombres y el espacio de nombres global) son una "reliquia de C veces" y deben evitarse. Todo lo contrario es verdad. Las funciones gratuitas permiten desacoplar funciones de clases específicas y permiten la reutilización de la funcionalidad. También se recomienda utilizar funciones gratuitas en lugar de funciones miembro si la función no necesita acceder a los detalles de implementación, ya que esto eliminará los cambios en cascada cuando se cambie la implementación de una clase, entre otras ventajas.

Esto también se refleja en el lenguaje: el bucle for basado en rango en C++0x (próxima versión de C ++ lanzada muy pronto) se basará en llamadas a funciones gratuitas. Obtendrá iteradores de inicio / final al llamar a las funciones gratuitas de begin y end .


un clásico entre principiantes a c ++ de c:

confundir delete y delete[]

EDITAR:

otra falla clásica entre todos los niveles de experiencia cuando se usa C API:

std::string helloString = "hello world"; printf("%s/n", helloString);

en lugar de:

printf("%s/n", helloString.c_str());

me pasa todas las semanas. Puede usar streams, pero a veces tiene que lidiar con API similares a printf.


Si una función acepta un puntero a un puntero, void* todavía lo hará

He visto que el concepto de un puntero de vacío se confunde con frecuencia. Se cree que si tienes un puntero, utilizas un void* , y si tienes un puntero a un puntero, utilizas un void** . Pero puede y debe en ambos casos usar void* . Un void** no tiene las propiedades especiales que tiene un void* .

Es una propiedad especial que a un void* también se le puede asignar un puntero a un puntero y cuando se devuelve se recibe el valor original.


Hehe, esta es una respuesta tonta: lo más incomprendido en la programación de C ++ son los mensajes de error de g ++ cuando las clases de plantillas no se compilan.


Dado este:

int x = sizeof(char);

que valor es X?

La respuesta que escucha a menudo depende del nivel de comprensión de la especificación.

  1. Principiante - x es uno porque los caracteres siempre son valores de ocho bits.
  2. Intermedio: depende de la implementación del compilador, los caracteres pueden ser del formato UTF16.
  3. Expert - x es uno y siempre será uno, ya que un char es la unidad de memoria direccionable más pequeña y sizeof determina el número de unidades de memoria requeridas para almacenar una instancia del tipo. Entonces en un sistema donde un char es de ocho bits, un valor de 32 bits tendrá un tamaño de 4; pero en un sistema donde un char es de 16 bits, un valor de 32 bits tendrá un tamaño de 2.

Es desafortunado que el estándar use ''byte'' para referirse a una unidad de memoria ya que muchos programadores piensan que ''byte'' es de ocho bits.