Peores prácticas en C ++, errores comunes [cerrado]

35

Después de leer este famoso discurso de Linus Torvalds , me pregunté cuáles son en realidad todas las trampas para los programadores en C ++. No me estoy refiriendo explícitamente a los errores tipográficos o al mal flujo del programa como se trata en esta pregunta y sus respuestas , sino a más errores de alto nivel que no son detectados por el compilador y que no producen errores obvios en la primera ejecución, errores de diseño completos, cosas que son improbables en C pero que probablemente sean hechas en C ++ por los recién llegados que no entienden las implicaciones completas de su código.

También acojo con beneplácito las respuestas que señalan una gran disminución del rendimiento donde generalmente no se esperaría. Un ejemplo de lo que uno de mis profesores me contó una vez sobre un generador de analizador LR (1) que escribí:

Ha utilizado demasiadas instancias de herencia y virtualidad innecesarias. La herencia hace que un diseño sea mucho más complicado (e ineficiente debido al subsistema RTTI (inferencia de tipo de tiempo de ejecución)) y, por lo tanto, solo debe usarse donde tenga sentido, por ejemplo, para las acciones en la tabla de análisis. Debido a que hace un uso intensivo de las plantillas, prácticamente no necesita herencia ".

Felix Dombek
fuente
66
Algunos de los errores más desagradables que puede cometer en C / C ++ se deben principalmente a la herencia de C ... lea el comportamiento indefinido, la gestión manual de la memoria, etc. Además, el consejo del profesor parece falso / incorrecto (para mí, quién no lo es un experto en C ++): la creación de instancias de plantilla debería producir una clase normal con vtable para virtualfunciones, ¿verdad?
8
O recuerdas mal lo que dijo tu profesor, o no tenía idea de lo que estaba hablando. Las clases derivadas generalmente no necesitan usar RTTI (reflexión AKA) para buscar cosas. Si están utilizando métodos virtuales, el código puede necesitar hacer una búsqueda de vtable para el envío, pero eso se traduce en una sola instrucción ASM en muchos procesadores. Debido a problemas de almacenamiento en caché, puede ralentizar las cosas en cierta cantidad, pero es poco probable que note la sobrecarga en los casos de uso que no sean los más exigentes. Hay muchas buenas razones para evitar C ++, pero las búsquedas de Vtable no son una de ellas.
Mason Wheeler
55
@FelixDombek: Dicho genéricamente y aplicado en todos los ámbitos, esa cita de tu profesor solo muestra una gran cantidad de ignorancia. Cuando su diseño necesita algún tipo de polimorfismo en tiempo de ejecución, el uso de funciones virtuales suele ser la mejor opción; cuando no lo necesite, no lo use: no necesita que todos los métodos sean virtuales solo porque usa clases derivadas, por ejemplo.
Fred Nurk
55
@Mason Wheeler: RTTI contiene información sobre el tipo, suficiente para poder determinar si una dynamic_castdebe tener éxito o no, y algunas otras cosas, pero la reflexión cubre mucho más, incluida la posibilidad de recuperar información sobre los atributos o funciones de los miembros, eso no es presente en C ++.
David Rodríguez - dribeas
55
El comentario del profesor es algo engañoso, ya que la herencia y las funciones virtuales no son un gran éxito en el rendimiento. El consejo de usar la herencia con moderación es bueno, pero es más un problema de estructura del programa que de eficiencia. La herencia, en particular con los miembros protegidos, es un acoplamiento lo más cercano posible, y si no lo necesita, no debe usarlo.
David Thornley

Respuestas:

69

Torvalds está hablando por el culo aquí.


De acuerdo, por qué está hablando por el culo:

En primer lugar, su perorata no es nada PERO despotricar. Hay muy poco contenido real aquí. La única razón por la que es realmente famoso o incluso ligeramente respetado es porque fue creado por el Dios de Linux. Su argumento principal es que C ++ es una mierda y le gusta molestar a la gente de C ++. Por supuesto, no hay ninguna razón para responder a eso y cualquiera que lo considere un argumento razonable está más allá de la conversación de todos modos.

En cuanto a lo que podría brillar como sus puntos más objetivos:

  • STL y Boost son una mierda absoluta <lo que sea. Eres un idiota.
  • STL y Boost causan infinitas cantidades de dolor <- ridículo. Obviamente está exagerando deliberadamente, pero ¿cuál es su verdadera declaración aquí? No lo sé. Hay algunos problemas más que trivialmente difíciles de resolver cuando provocas el vómito del compilador en Spirit o algo así, pero no es más o menos difícil de resolver que la depuración de UB causada por el mal uso de construcciones C como void *.
  • Los modelos abstractos alentados por C ++ son ineficientes. <- ¿Como qué? Nunca se expande, nunca proporciona ningún ejemplo de lo que quiere decir, solo lo dice. BFD Como no puedo decir a qué se refiere, no tiene sentido tratar de "refutar" la declaración. Es un mantra común de los fanáticos de C, pero eso no lo hace más comprensible o inteligible.
  • El uso correcto de C ++ significa que te limitas a los aspectos de C. <- En realidad, el código PEOR C ++ por ahí hace esto, así que todavía no sé de qué está hablando WTF.

Básicamente, Torvalds está hablando por el culo. No hay argumentos inteligibles sobre nada. Esperar una refutación seria de tales tonterías es simplemente una tontería. Me dicen que "expanda" una refutación de algo sobre lo que se espera que amplíe si es donde yo lo dije. Si realmente, honestamente, mira lo que dijo Torvalds, verías que en realidad no dijo nada.

Solo porque Dios dice que no significa que tenga sentido o que deba tomarse más en serio que si un bozo al azar lo dijera. A decir verdad, Dios es solo otro bozo al azar.


Respondiendo a la pregunta real:

Probablemente, la peor y más común práctica incorrecta de C ++ es tratarla como C. El uso continuo de las funciones de C API como printf, gets (también considerado malo en C), strtok, etc. no solo no logran aprovechar la potencia proporcionada. por el sistema de tipo más estricto, inevitablemente conducen a más complicaciones al tratar de interactuar con el código C ++ "real". Básicamente, haga exactamente lo contrario de lo que Torvalds está recomendando.

Aprenda a aprovechar el STL y Boost para obtener una mayor detección de errores en el tiempo de compilación y hacer su vida más fácil de otras maneras generales (el tokenizer boost, por ejemplo, es de tipo seguro Y una mejor interfaz). Es cierto que tendrá que aprender a leer los errores de la plantilla, lo cual es desalentador al principio, pero (en mi experiencia de todos modos) es francamente mucho más fácil que tratar de depurar algo que genera un comportamiento indefinido durante el tiempo de ejecución, que hace la API C Muy fácil de hacer.

No quiere decir que C no sea tan bueno. Por supuesto, me gusta C ++ mejor. A los programadores de C les gusta C mejor. Hay compensaciones y gustos subjetivos en el juego. También hay mucha información errónea y FUD flotando. Diría que hay más FUD y desinformación flotando sobre C ++, pero soy parcial en este sentido. Por ejemplo, los problemas de "hinchazón" y "rendimiento" que supuestamente tiene C ++ no son en realidad problemas importantes la mayoría de las veces y, ciertamente, están fuera de las proporciones de la realidad.

En cuanto a los problemas a los que se refiere su profesor, estos no son exclusivos de C ++. En OOP (y en programación genérica) desea preferir la composición sobre la herencia. La herencia es la relación de acoplamiento más fuerte posible que existe en todos los lenguajes OO. C ++ agrega uno más que es más fuerte, la amistad. La herencia polimórfica debe usarse para representar abstracciones y relaciones "es-a", nunca debe usarse para su reutilización. Este es el segundo error más grande que puede cometer en C ++, y es bastante grande, pero está lejos de ser exclusivo del lenguaje. También puede crear relaciones de herencia demasiado complejas en C # o Java, y tendrán exactamente los mismos problemas.

Edward extraño
fuente
1
Irónico, como hasta mucho después de 2007, git solo ejecutó versiones portátiles de Linux. Bueno, cualquier sistema que fuera unix-like. Por otra parte, dadas las circunstancias que llevaron a la creación de git, ciertamente no lo estoy sosteniendo contra él.
Chris K
99
Linus tiene dificultades para encontrar buenos programadores de C ++ que quieran trabajar para él. ¿Preguntarse por qué? Creo que esto es solo un tipo de problema de huevo y gallina.
Bo Persson
19

Siempre he pensado que los peligros de C ++ fueron muy exagerados por los programadores inexpertos de C with Classes.

Sí, C ++ es más difícil de aprender que algo como Java, pero si programa utilizando técnicas modernas, es bastante fácil escribir programas robustos. Sinceramente, no tengo que mucho más difícil de una programación horaria en C ++ que yo en lenguajes como Java, y a menudo me encuentro que faltan ciertas abstracciones C ++ como plantillas y RAII cuando diseño en otros idiomas.

Dicho esto, incluso después de años de programación en C ++, de vez en cuando cometeré un error realmente estúpido que no sería posible en un lenguaje de nivel superior. Un error común en C ++ es ignorar la vida útil de los objetos: en Java y C # generalmente no tiene que preocuparse por la vida útil de los objetos *, porque todos los objetos existen en el montón y son administrados por un recolector de basura mágico.

Ahora, en C ++ moderno, por lo general , tampoco necesita preocuparse demasiado por la vida útil de los objetos. Tiene destructores e indicadores inteligentes que administran la vida útil de los objetos por usted. El 99% de las veces, esto funciona de maravilla. Pero de vez en cuando, un puntero colgante (o referencia) lo atornillará. Por ejemplo, recientemente tuve un objeto (llamémoslo Foo) que contenía una variable de referencia interna a otro objeto (llamémoslo Bar). En un momento, estúpidamente arreglé las cosas para que Barsalieran antes del alcance Foo, pero Fooel destructor terminó llamando a una función miembro de Bar. No hace falta decir que las cosas no salieron bien.

Ahora, realmente no puedo culpar a C ++ por esto. Era mi propio mal diseño, pero el punto es que este tipo de cosas no sucedería en un lenguaje administrado de nivel superior. Incluso con punteros inteligentes y similares, a veces aún debe tener una conciencia del tiempo de vida del objeto.


* Si el recurso que se administra es memoria, es decir.

Charles Salvia
fuente
8
¿Nunca tiene que preocuparse por la vida útil de los objetos en Java y C #? Su GC se encarga de la memoria, pero eso es solo una pequeña parte de RAII para mí; mire las diversas interfaces "desechables" que tienen esos idiomas, por ejemplo.
Fred Nurk
Tener que preocuparse por la vida útil de los objetos sería raro en Java, excepto por el diseño inconveniente de su biblioteca de E / S.
dan04
Su problema de referencia pendiente es algo que estoy interesado en tratar de resolver. Comencé una discusión en mi blog sobre la dirección en la que me dirijo para resolverlo (promesas de puntero). Básicamente creo que el lenguaje podría usar algunos punteros más inteligentes. Participe en esa discusión si está interesado. Nadie más ha sido así que lo que sea ... pero si es algo que le gustaría ver resuelto ... De hecho, me encuentro con el problema mucho más del 10% del tiempo.
Edward Strange
13

La diferencia en el código suele estar más relacionada con el programador que con el lenguaje. En particular, un buen programador de C ++ y un programador de C llegarán a soluciones igualmente buenas (aunque diferentes). Ahora, C es un lenguaje más simple (como lenguaje) y eso significa que hay menos abstracciones y más visibilidad sobre lo que el código realmente hace.

Una parte de su diatriba (es conocido por sus diatribas contra C ++) se basa en el hecho de que más personas tomarán C ++ y escribirán código sin comprender realmente lo que algunas de las abstracciones ocultan y hacen suposiciones erróneas.

David Rodríguez - dribeas
fuente
3
¿Cuál es el costo de iterar sobre un std::vector<bool>cambio de cada valor? for ( std::vector<bool>::iterator it = v.begin(), end = v.end(); it != end; ++it ) { *it = !*it; }? ¿En qué se abstrae *it = !*it;?
David Rodríguez - dribeas
2
Aunque puede ser injusto elegir lenguaje específico abominaciones ampliamente criticadas como errores ...
Fred Nurk
2
@ Fred Nurk: std::vector<bool>es un error bien conocido, pero es un muy buen ejemplo de lo que se está discutiendo: las abstracciones son buenas, pero hay que tener cuidado con lo que ocultan. Lo mismo puede suceder y sucederá en el código de usuario. Para empezar, he visto que tanto las personas en C ++ como en Java usan excepciones para realizar el control de flujo, y un código que parece una llamada de función de anidación que en realidad es un iniciador de excepciones de rescate: void endOperation();implementado como throw EndOperation;. Un buen programador evitará esas construcciones sorprendentes , pero el hecho es que puedes encontrarlas.
David Rodríguez - dribeas
55
Uno de los puntos de Torvalds es que: puede alejar a los principiantes simplemente eligiendo C sobre C ++ (parece que hay más principiantes de C ++) y C ++ es más complejo tiene una curva de aprendizaje más pronunciada y hay más posibilidades de tropezar en un caso de esquina .
David Rodríguez - dribeas
2
+1, esto es exactamente de lo que se queja Linus. Parece ser anti-C ++, pero en realidad no es así. Él es solo anti-C ++ - programador.
greyfade
13

Uso excesivo de try/catchbloques.

File file("some.txt");
try
{
  /**/

  file.close();
}
catch(std::exception const& e)
{
  file.close();
}

Esto generalmente proviene de lenguajes como Java y la gente argumentará que C ++ carece de una finalizecláusula.

Pero este código exhibe dos problemas:

  • Es necesario construir fileantes del try/catch, porque en realidad closeno puede existir un archivo que no exista catch. Esto lleva a una "fuga de alcance" que filees visible después de haber sido cerrada. Puede agregar un bloque pero ...: /
  • Si alguien aparece y agrega un returnen medio del tryalcance, entonces el archivo no está cerrado (razón por la cual las personas se quejan de la falta de finalizecláusula)

Sin embargo, en C ++, tenemos formas mucho más eficientes de tratar este problema que:

  • De Java finalize
  • C # 's using
  • Ir defer

Tenemos RAII, cuya propiedad realmente interesante se resume mejor como SBRM(Scoped Bound Resources Management).

Al crear la clase de modo que su destructor limpie los recursos que posee, ¡no tenemos la responsabilidad de administrar el recurso en todos y cada uno de sus usuarios!

Esta es la característica que extraño en cualquier otro idioma, y ​​probablemente la que más se olvida.

La verdad es que rara vez es necesario incluso escribir un try/catchbloque en C ++, aparte en el nivel superior para evitar la terminación sin iniciar sesión.

Matthieu M.
fuente
1
Yo no creo que sea la influencia de Java tanto como de C. (Se puede sustituir directamente fopeny fcloseaquí.) RAII es la manera "correcta" de hacer las cosas aquí, pero es un inconveniente para las personas que quieren utilizar bibliotecas de C de C ++ .
dan04
Para este tipo de respuesta, sería apropiado proporcionar un ejemplo de la solución correcta.
Claus Jørgensen
@ ClausJørgensen: Bueno, desafortunadamente, la solución no es realmente "llamativa" ya que involucra solo File file("some.txt");y eso es todo (no open, no close, no try...)
Matthieu M.
D también tiene RAII
Demi
@Demetri: No estoy muy familiarizado con D, ¿podría explicar cómo RAII interactúa con la recolección de basura? Sé que en Python puede escribir un método "deinit", sin embargo, la documentación advierte que en caso de ciclo de referencias, algunos objetos no verán llamado su método deinit.
Matthieu M.
9

Un error común que se ajusta a sus criterios es no entender cómo funcionan los constructores de copias cuando se trata de memoria asignada en su clase. Perdí la cuenta de la cantidad de tiempo que pasé arreglando fallas o pérdidas de memoria porque un 'novato' colocó sus objetos en un mapa o vector y no escribió los constructores y destructores de copias correctamente.

Desafortunadamente, C ++ está lleno de trampas 'ocultas' como esta. Pero quejarse de eso es como quejarse de que fue a Francia y no podía entender lo que la gente decía. Si vas a ir allí, aprende el idioma.

Enrique
fuente
1
Creo que el problema con C ++ es que es muy fácil dispararse en el pie. Claro, hay buenos programadores de C ++, muchos buenos programas escritos en C ++. Pero es muy difícil convertirse en un buen desarrollador de C ++. La serie Efficient C ++ de Scott Meyers muestra cuántas sutilezas tiene el lenguaje.
Marco Mustapic
Estoy de acuerdo. Sin embargo, parte del problema es que muchos (la mayoría) de los programadores de C ++ piensan que saben lo que están haciendo cuando claramente no lo hacen. ¿Quiso decir "C ++ eficaz"?
Henry
Al menos esto está mejorando con las nuevas reglas bastante restrictivas sobre la generación implícita de operaciones de copiar / mover en C ++ 0x. En muchos de los casos de violación de la regla de tres, la generación implícita de operaciones de copia quedará en desuso y debería generar una advertencia.
sellibitze
6

C ++ permite una gran variedad de características y estilos de programación, pero eso no significa que estas sean realmente buenas formas de utilizar C ++. Y de hecho, es increíblemente fácil usar C ++ incorrectamente.

Tiene que ser aprendido y entendido correctamente , solo aprender haciendo (o usarlo como si se usara otro idioma) conducirá a un código ineficiente y propenso a errores.

Darío
fuente
4

Bueno ... Para empezar, puedes leer las preguntas frecuentes de C ++ Lite

Luego, varias personas han construido carreras escribiendo libros sobre las complejidades de C ++:

Herb Sutter y Scott Meyers a saber.

En cuanto a la falta de sustancia de Torvalds ... venga gente, en serio: ningún otro idioma ha derramado tanta tinta sobre el tratamiento de los matices del idioma. Sus libros de Python, Ruby y Java se centran en aplicaciones de escritura ... sus libros de C ++ se centran en características / consejos / trampas de lenguaje tonto.

tierra roja
fuente
1
Hmm ... javapuzzlers.com , jimbrooks.org/web/python/#Pitfalls . Yo diría que C ++ acelerado (por ejemplo) se centra mucho más en cómo escribir código que estos ...
Jerry Coffin
1
Has presentado un par de ejemplos de recursos que señalan casos extremos en sus respectivos idiomas; cosas que parecen extrañas y no estás seguro de cómo funcionarían (aunque las cosas de la lista de Python están cerca) ... C ++ tiene una industria completa que señala cosas que parecen perfectamente válidas y que se comportan de una manera que no esperas.
suciedad roja
3

Las plantillas demasiado pesadas pueden no provocar errores al principio. Sin embargo, a medida que pase el tiempo, las personas necesitarán modificar ese código, y tendrán dificultades para comprender una plantilla enorme. Ahí es cuando entran los errores: los malentendidos provocan comentarios de "Compila y ejecuta", que a menudo conducen a un código casi correcto.

En general, si me veo haciendo una plantilla genérica profunda de tres niveles, me detengo y pienso cómo podría reducirse a una. A menudo, el problema se resuelve extrayendo funciones o clases.

Michael K
fuente
8
Mantener un código complicado frente a los requisitos cambiantes siempre causa errores sin mucho esfuerzo, nada particularmente especial sobre las plantillas allí.
Fred Nurk
2

Advertencia: esto no es tanto una respuesta como una crítica de la charla que "usuario desconocido" vincula en su respuesta.

Su primer punto principal es el (supuestamente) "estándar siempre cambiante". En realidad, todos los ejemplos que da se relacionan con cambios en C ++ antes de que hubiera un estándar. Desde 1998 (cuando se finalizó el primer estándar de C ++) los cambios en el lenguaje han sido bastante mínimos; de hecho, muchos argumentan que el verdadero problema es que deberían haberse realizado más cambios. Estoy razonablemente seguro de que todo el código que se ajustaba al estándar original de C ++ todavía se ajusta al estándar actual. Aunque es algo menos seguro, a menos que algo cambie rápidamente (y de manera bastante inesperada), lo mismo será bastante cierto con el próximo estándar C ++ también (en teoría, todo el código que usóexportse romperá, pero prácticamente no existe ninguno; desde un punto de vista práctico no es un problema). Puedo pensar en algunos otros idiomas, sistemas operativos (o mucho más relacionados con la computadora) que puedan hacer tal afirmación.

Luego entra en "estilos siempre cambiantes". Una vez más, la mayoría de sus puntos están bastante cerca de tonterías. Intenta caracterizarlo for (int i=0; i<n;i++)como "viejo y reventado" y for (int i(0); i!=n;++i)"nuevo calor". La realidad es que si bien existen tipos para los que dichos cambios podrían tener sentido, intya que no hay diferencia, e incluso cuando se puede obtener algo, rara vez es necesario escribir un código correcto o correcto. Incluso en el mejor de los casos, está haciendo una montaña de un topo.

Su próximo reclamo es que C ++ está "optimizando en la dirección equivocada", específicamente, aunque admite que usar buenas bibliotecas es fácil, afirma que C ++ "hace que escribir buenas bibliotecas sea casi imposible". Aquí, creo que es uno de sus errores más fundamentales. En realidad, escribir buenas bibliotecas para casi cualquier idioma es extremadamente difícil. Como mínimo, escribir una buena biblioteca requiere comprender algunos dominios problemáticos tan bien que su código funciona para una multitud de posibles aplicaciones en (o relacionadas con) ese dominio. La mayor parte de lo que C ++ realmente hace es "elevar el listón": después de ver cuán mejor puede ser una biblioteca , las personas rara vez están dispuestas a volver a escribir el tipo de basura que tendrían de lo contrario.los codificadores realmente buenos escriben bastantes bibliotecas, que luego pueden ser utilizadas (fácilmente, como él admite) por "el resto de nosotros". Este es realmente un caso donde "eso no es un error, es una característica".

No trataré de llegar a cada punto en orden (eso tomaría páginas), pero saltaré directamente a su punto de cierre. Cita a Bjarne diciendo: "la optimización de todo el programa se puede utilizar para eliminar tablas de funciones virtuales y datos RTTI no utilizados. Tal análisis es particularmente adecuado para programas relativamente pequeños que no usan enlaces dinámicos".

Él critica esto haciendo una afirmación sin respaldo de que "Este es un problema realmente difícil", incluso yendo tan lejos como comparándolo con el problema de detención. En realidad, no es nada de eso, de hecho, el enlazador incluido con Zortech C ++ (más o menos el primero compilador de C ++ para MS-DOS, en la década de 1980) hizo esto. Es cierto que es difícil estar seguro de que se hayan eliminado todos los datos posiblemente extraños, pero sigue siendo razonable hacer un trabajo bastante justo.

Sin embargo, independientemente de eso, el punto mucho más importante es que esto es completamente irrelevante para la mayoría de los programadores en cualquier caso. Como aquellos de nosotros que hemos desarmado bastante código sabemos, a menos que escriba lenguaje ensamblador sin ninguna biblioteca, sus ejecutables casi seguramente contienen una buena cantidad de "cosas" (código y datos, en casos típicos) que usted probablemente ni siquiera sé sobre eso, sin mencionar el uso real. Para la mayoría de las personas, la mayoría de las veces, simplemente no importa: a menos que esté desarrollando para los sistemas integrados más pequeños, ese consumo de almacenamiento adicional es simplemente irrelevante.

Al final, es cierto que esta diatriba tiene un poco más de sustancia que la idiotez de Linus, pero eso le da exactamente la condena con elogios que merece.

Jerry Coffin
fuente
1

Como programador en C que tuvo que codificar en C ++ debido a circunstancias inevitables, aquí está mi experiencia. Hay muy pocas cosas que utilizo que son C ++ y la mayoría se adhieren a C. La razón principal es porque no entiendo C ++ tan bien. Tenía / no tenía un mentor que me mostrara las complejidades de C ++ y cómo escribir un buen código en él. Y sin la guía de un muy buen código de C ++, es extremadamente difícil escribir un buen código en C ++. En mi humilde opinión, este es el mayor inconveniente de C ++ porque los buenos codificadores de C ++ dispuestos a manejar principiantes son difíciles de encontrar.

Algunos de los éxitos de rendimiento que he visto generalmente se deben a la asignación de memoria mágica de STL (sí, puede cambiar el asignador, pero ¿quién lo hace cuando comienza con C ++?). Usualmente escuchas argumentos de expertos en C ++ de que los vectores y las matrices ofrecen un rendimiento similar, porque los vectores usan matrices internamente y la abstracción es súper eficiente. He encontrado que esto es cierto en la práctica para el acceso de vectores y la modificación de los valores existentes. Pero no es cierto para agregar una nueva entrada, construcción y destrucción de vectores. gprof mostró que el 25% del tiempo acumulado para una aplicación se gastó en constructores de vectores, destructores, memmove (para la reubicación de todo el vector para agregar un nuevo elemento) y otros operadores de vectores sobrecargados (como ++).

En la misma aplicación, se usó el vector de somethingSmall para representar un somethingBig. No había necesidad de acceso aleatorio de algo pequeño en algo grande. Todavía se usó un vector en lugar de una lista. ¿La razón por la que se usó el vector? Porque el codificador original estaba familiarizado con la matriz como la sintaxis de vectores y no estaba muy familiarizado con los iteradores necesarios para las listas (sí, él es de un fondo C). Continúa para demostrar que se necesita mucha orientación de expertos para obtener C ++ correctamente. C ofrece tan pocas construcciones básicas sin absolutamente ninguna abstracción, que puede hacerlo correctamente mucho más fácilmente que C ++.

aufather
fuente
0

STL y boost son portátiles, a nivel de código fuente. Supongo que de lo que habla Linus es de que C ++ carece de una ABI (interfaz binaria de aplicación). Por lo tanto, debe compilar todas las bibliotecas con las que se vincula, con la misma versión del compilador y con los mismos modificadores, o limítese al C ABI en las bibliotecas dll. También encuentro que annyoing ... pero a menos que esté haciendo bibliotecas de terceros, debería poder tomar el control de su entorno de compilación. Me parece que restringirme al C ABI no vale la pena. La conveniencia de poder pasar cadenas, vectores y punteros inteligentes de un dll a otro merece la pena tener que reconstruir todas las bibliotecas al actualizar compiladores o cambiar los conmutadores de compilador. Las reglas de oro que sigo son:

- Heredar para reutilizar la interfaz, no la implementación

-Preferir la agregación sobre la herencia

-Preferir, siempre que sea posible, funciones gratuitas a los métodos miembros

-Siempre use el lenguaje RAII para hacer que su código sea totalmente seguro. Evite intentar atrapar.

-Utilice punteros inteligentes, evite punteros desnudos (sin dueño)

-Preferir semántica de valor a semántica de referencia

-No reinventes la rueda, usa stl y boost

-Utilice el idioma Pimpl para ocultar privado y / o para proporcionar un firewall compilador


fuente
-6

No poner una final ;al final de una declaración de clase, al menos en algunas versiones de VC.

Marco Mustapic
fuente
44
Este es quizás un error muy común para los principiantes (como lo es casi cualquier cosa para alguien que todavía está aprendiendo la sintaxis básica), pero ¿hay muchos que se consideren competentes y todavía consideren que este error es notable?
Fred Nurk
1
Lo escribí solo porque el compilador le dio un error que no tenía nada que ver con la falta de un punto y coma.
Marco Mustapic
2
sí, exactamente el mismo error es lo que obtienes de un compilador de C.
Mircea Chirea