En mi opinión, los peligros de C ++ son algo exagerados.
El peligro esencial es este: mientras C # le permite realizar operaciones de puntero "inseguras" utilizando unsafe
palabra clave, C ++ (que en su mayoría es un superconjunto de C) le permitirá usar punteros cuando lo desee. Además de los peligros habituales inherentes al uso de punteros (que son los mismos con C), como pérdidas de memoria, desbordamientos de búfer, punteros colgantes, etc., C ++ presenta nuevas formas para que arruines las cosas.
Esta "soga extra", por así decirlo, de la que Joel Spolsky estaba hablando , básicamente se reduce a una cosa: escribir clases que manejan internamente su propia memoria, también conocida como la " Regla de 3 " (que ahora se puede llamar la Regla de 4 o regla de 5 en C ++ 11). Esto significa que si alguna vez desea escribir una clase que administre sus propias asignaciones de memoria internamente, debe saber lo que está haciendo o su programa probablemente se bloqueará. Debe crear cuidadosamente un constructor, un constructor de copia, un destructor y un operador de asignación, que es sorprendentemente fácil de equivocar, lo que a menudo resulta en extraños bloqueos en el tiempo de ejecución.
SIN EMBARGO , en la programación real de C ++ todos los días, es muy raro escribir una clase que administre su propia memoria, por lo que es engañoso decir que los programadores de C ++ siempre deben ser "cuidadosos" para evitar estos escollos. Por lo general, solo harás algo más como:
class Foo
{
public:
Foo(const std::string& s)
: m_first_name(s)
{ }
private:
std::string m_first_name;
};
Esta clase se parece bastante a lo que haría en Java o C #: no requiere una administración de memoria explícita (porque la clase de la biblioteca std::string
se encarga de todo eso automáticamente), y no se requiere nada de "Regla de 3" desde el valor predeterminado El constructor de copia y el operador de asignación están bien.
Solo cuando intentas hacer algo como:
class Foo
{
public:
Foo(const char* s)
{
std::size_t len = std::strlen(s);
m_name = new char[len + 1];
std::strcpy(m_name, s);
}
Foo(const Foo& f); // must implement proper copy constructor
Foo& operator = (const Foo& f); // must implement proper assignment operator
~Foo(); // must free resource in destructor
private:
char* m_name;
};
En este caso, puede ser complicado para los principiantes obtener la asignación, el destructor y el constructor de copia correctos. Pero para la mayoría de los casos, no hay razón para hacer esto. C ++ hace que sea muy fácil evitar la gestión manual de la memoria el 99% del tiempo mediante el uso de clases de biblioteca como std::string
y std::vector
.
Otro problema relacionado es la gestión manual de la memoria de una manera que no tiene en cuenta la posibilidad de que se produzca una excepción. Me gusta:
char* s = new char[100];
some_function_which_may_throw();
/* ... */
delete[] s;
Si some_function_which_may_throw()
en realidad no lanzar una excepción, uno se queda con una pérdida de memoria debido a que la memoria asignada para s
que nunca se recuperó. Pero, de nuevo, en la práctica esto ya no es un problema por la misma razón por la que la "Regla de 3" ya no es realmente un problema. Es muy raro (y generalmente innecesario) administrar su propia memoria con punteros sin formato. Para evitar el problema anterior, todo lo que debe hacer es usar un std::string
o std::vector
, y el destructor se invocará automáticamente durante el desenrollado de la pila después de que se haya lanzado la excepción.
Por lo tanto, un tema general aquí es que muchas características de C ++ que no se heredaron de C, como la inicialización / destrucción automática, los constructores de copias y las excepciones, obligan a un programador a tener mucho cuidado al hacer la gestión manual de la memoria en C ++. Pero, de nuevo, esto es solo un problema si tiene la intención de hacer una gestión manual de la memoria en primer lugar, lo que casi nunca es necesario cuando se tienen contenedores estándar y punteros inteligentes.
Por lo tanto, en mi opinión, aunque C ++ le proporciona una gran cantidad de soga adicional, casi nunca es necesario usarlo para ahorcarse, y las trampas de las que Joel hablaba son trivialmente fáciles de evitar en C ++ moderno.
Your questions should be reasonably scoped. If you can imagine an entire book that answers your question, you’re asking too much.
. Creo que esto califica como tal pregunta ...