¿Características C ++ de "todo el equipo"?

16

En C ++, características como las excepciones afectan a todo el programa: puede deshabilitarlas en todo el programa o debe tratarlas en todo el código. Como dice un famoso artículo sobre C ++ Report :

Contra intuitivamente, la parte difícil de las excepciones de codificación no son los lanzamientos y capturas explícitos. La parte realmente difícil de usar excepciones es escribir todo el código intermedio de tal manera que una excepción arbitraria pueda propagarse desde su sitio de lanzamiento a su controlador, llegando de manera segura y sin dañar otras partes del programa en el camino.

Dado que incluso newarroja excepciones, cada función debe proporcionar seguridad de excepción básica , a menos que solo llame a funciones que garanticen que no se arroje ninguna excepción, a menos que desactive las excepciones por completo en todo su proyecto .

Por lo tanto, las excepciones son una característica de "todo el programa" o "todo el equipo", ya que deben ser entendidas por todos en un equipo que las usa. Pero no todas las características de C ++ son así, que yo sepa.

Un posible ejemplo es que si no obtengo plantillas pero no las uso, aún podré escribir C ++ correcto, ¿o no? Incluso puedo invocar sortuna variedad de enteros y disfrutar de su sorprendente ventaja de velocidad wrt. C qsort(porque no se llama a ningún puntero de función), sin arriesgar errores, ¿o no? Parece que las plantillas no son "todo el equipo".

¿Existen otras características de C ++ que afectan el código que no las usa directamente y, por lo tanto, son "todo un equipo"? Estoy especialmente interesado en características que no están presentes en C.

Actualización : estoy especialmente buscando características en las que no hay signos de lenguaje obligatorio que necesita tener en cuenta. La primera respuesta que obtuve mencionó la corrección constante, que también es un equipo completo, por lo tanto, todo el mundo necesita aprender al respecto; sin embargo, AFAICS lo afectará solo si llama a una función que está marcada const, y el compilador evitará que lo llame a objetos no constantes, por lo que obtendrá algo para google. Con excepciones, ni siquiera lo entiendes; Además, siempre se usan tan pronto como se usa new, por lo tanto, las excepciones son más "insidiosas". Sin embargo, como no puedo expresar esto de manera objetiva, agradeceré cualquier característica de todo el equipo.

Actualización 2 : en lugar de la función C ++, debería haber escrito algo así como "función específica de C ++", para excluir cosas como el subprocesamiento múltiple que se aplican a una gran cantidad de lenguajes de programación convencionales.

Apéndice: ¿Por qué esta pregunta es objetiva?

C ++ es un lenguaje complejo, por lo que muchos proyectos o guías de codificación intentan seleccionar características "simples" de C ++, y muchas personas intentan incluir o excluir algunas según criterios principalmente subjetivos. Las preguntas sobre eso se cierran con regularidad aquí en SO.

Arriba, en cambio, definí (de la manera más precisa posible) qué es una característica del lenguaje de "todo el equipo", proporcioné un ejemplo (excepciones), junto con una amplia evidencia de apoyo en la literatura sobre C ++, y solicité características de todo el equipo en C ++ más allá de las excepciones.

Si debe usar características de "todo el equipo", o si ese es un concepto relevante, puede ser subjetivo, pero eso solo significa que la importancia de esta pregunta es subjetiva, como siempre.

Blaisorblade
fuente

Respuestas:

11

Nominaría la concurrencia como una característica de "todo el equipo".

Aunque es posible diseñar el software de manera que solo unos pocos expertos necesiten conocer los problemas de concurrencia y el resto del equipo pueda cosechar los beneficios sin preocuparse por las complejidades (como puede hacer con las plantillas), en la práctica sí No funciona de esa manera. En la práctica, si tiene varios subprocesos, debe analizar cuidadosamente cada variable que use si hay posibles problemas de concurrencia con ese uso.

Bart van Ingen Schenau
fuente
Estoy de acuerdo en que los hilos son características de todo un equipo, aunque no son específicos de C ++. Sin embargo, también hay otras interfaces para la concurrencia (no basadas en hilos), principalmente en otros idiomas, y algunas permiten que la concurrencia se encapsule mucho mejor (aunque este sigue siendo un tema de investigación actual en lenguajes de programación). Por lo tanto, es una pregunta abierta si esto se aplica a la concurrencia per-se.
Blaisorblade
@Blaisorblade: C ++ 11 introdujo su propia biblioteca de subprocesos, así que sí, ahora es parte de C ++.
Michael Kohne
@MichaelKohne: No dije que C ++ no sea compatible con subprocesos múltiples. Dije que los hilos no son específicos de C ++, porque muchos otros lenguajes los tienen. Acabo de señalar que los problemas descritos se aplican a los hilos como una interfaz para la concurrencia.
Blaisorblade
Yo diría que "condición de carrera" es una mejor palabra para este tema central. Es decir, es posible que los programadores no necesiten trabajar o usar el marco de concurrencia en absoluto, pero si escriben algún código C ++, y su código podría llamarse potencialmente desde más de un hilo, entonces deben pensar en las condiciones de carrera en general, en todo su código escrito.
rwong
Me recuerda una falta de comunicación con un compañero de trabajo que sucedió hace años. Un compañero de trabajo le preguntó a otro compañero de trabajo: ¿es esto (alguna función) seguro para subprocesos? El otro compañero de trabajo respondió que sí. El compañero de trabajo que preguntó luego lo usó desde varios subprocesos y obtuvo resultados inesperados (no se bloqueó, pero se aplicaron múltiples operaciones en el mismo objeto). Resultó que el compañero de trabajo que preguntó no tenía el modelo mental de lo que significa "seguro para subprocesos", y confundió la respuesta como "puedo hacer lo que quiera".
rwong el
10

La respuesta obvia es la constcorrección: dado que const/ volatilecalificación es infecciosa, una vez que una parte del código comenzó a usarlo, todos los códigos de llamada (directa o indirectamente) también deben ser constcorrectos o descartarse constexplícitamente.

Sin embargo, como con las excepciones, esto es, en última instancia, algo bueno . Más aún, porque a diferencia de la seguridad de excepción, el compilador lo verifica estrictamente.

Konrad Rudolph
fuente
2
Además, la constcorrección es transparente: solo se trata del tipo que le das a una función (que siempre está visible) y el compilador te gritará si te equivocas. Estaba pensando en cosas más opacas, en las que no tienes idea de que algo anda mal hasta que es demasiado tarde (e incluso entonces, será difícil resolverlo). Pero su respuesta es interesante de todos modos, por lo tanto, votó positivamente.
Blaisorblade
10

Punteros

  • ¿El puntero apunta a la memoria en la pila?
  • ¿El puntero apunta a la memoria en el montón?
  • ¿El puntero apunta a un solo objeto?
  • ¿El puntero apunta a una matriz?
  • ¿El puntero apunta a una ubicación en el medio de una matriz?
  • ¿Es válido el puntero?
  • ¿El puntero está destrozado?
  • ¿Qué código "posee" el puntero?
  • ¿Debe el objeto referenciado ser desasignado manualmente? ¿Si es así, cómo?
Thomas Eding
fuente
1
+1 específicamente debido a la pregunta sobre la propiedad del puntero. Sin punteros inteligentes, la propiedad realmente se propaga por todo el equipo.
JKor
3

Otra posibilidad es la sobrecarga del operador. Una vez que una parte de la base de código comienza a jugar con operadores sobrecargados todo el mundo tiende a comenzar la segunda adivinar qué objeto simplemente exactamente cualquier dado que está trabajando es en realidad haciendo. No se propaga explícitamente a través de la base de código de la forma en que lo hacen las excepciones y la corrección constante, pero definitivamente es algo que puede comenzar a causar problemas si todo el equipo no está en la misma página sobre cuándo, cómo y por qué usarlo.

Evicatos
fuente
1

Lo único que viene a la mente además de la corrección constante (visto anteriormente) es el estado de flujo (ing). Si escribe código C ++ donde usa objetos y subobjetos y es probable que haya jerarquías de objetos, eventualmente querrá enviar o recibir datos hacia / desde el operador del programa. Usted puede escribir las operaciones de transmisión simples que se compilan y se semánticamente correcta ...

std::ostream& operator<< (std::ostream&, MyClass const&) {...}
std::istream& operator>> (std::istream&, MyClass&) {...}

... Pero una vez que lo haga, nunca tendrá ninguna garantía de que lo que está tratando de escribir (o lo más importante, leer) sigue el mismo formato que lo que el cliente le está enviando. Hay demasiados casos de rareza en las transmisiones, incluso peor si tiene que pasar transmisiones o banderas de transmisiones como argumentos en su cadena de llamadas de función ... que es como se implementa generalmente la transmisión de clases. Por lo tanto, la transmisión puede definirse como "insidiosa" como usó el término anterior, o tal vez incluso como "viral" ( aunque no en cualquier lugar en el mismo grado que la corrección constante ).

¿Tiene un miembro en el fondo de su jerarquía de clases que es un string? Sorpresa, el cliente mejor envía una sola palabra, o de lo contrario. ¿Tienes algunos números que quieres serializar? Es mejor que verifique, guarde y restaure los indicadores de flujo en cada profundidad de llamada de función, porque nunca sabe quién es el idiota que acaba de configurar su flujo en salida octal antes de llamar a su función. O peor: quién acaba de llamar a algo así setfilly, por lo setwtanto, rompió el formato de entrada / salida de sus primeros miembros integrales, y solo sus primeros, porque esos estados no se propagan . Ah, y no preguntemos por las transmisiones y la internacionalización.

No hay ninguna advertencia en el idioma que esté transmitiendo de la manera correcta o incorrecta, o incluso transmitiendo en absoluto . ¿Se le solicitó el código de cliente para que se pase una secuencia para escribir una copia de seguridad de datos? Realmente no tienes una manera de saber a qué apunta la secuencia /dev/null. (¡ Por otro lado, puede reclamar increíbles velocidades de respaldo y tasas de compresión de esa manera! )

Luis Machuca
fuente