Na minha opinião, os perigos do C ++ são um pouco exagerados.
O perigo essencial é este: enquanto o C # permite executar operações de ponteiro "inseguras" usando a unsafepalavra - chave, o C ++ (sendo principalmente um superconjunto de C) permite usar ponteiros sempre que lhe apetecer. Além dos perigos usuais inerentes ao uso de ponteiros (que são iguais a C), como vazamentos de memória, estouros de buffer, ponteiros pendentes, etc., o C ++ apresenta novas maneiras de você estragar seriamente as coisas.
Essa "corda extra", por assim dizer, sobre a qual Joel Spolsky estava falando , basicamente se resume a uma coisa: escrever aulas que gerenciam internamente sua própria memória, também conhecida como " Regra dos 3 " (que agora pode ser chamada de Regra de 4 ou regra de 5 em C ++ 11). Isso significa que, se você quiser escrever uma classe que gerencia internamente suas próprias alocações de memória, é necessário saber o que está fazendo ou o programa provavelmente falhará. É necessário criar cuidadosamente um construtor, construtor de cópias, destruidor e operador de atribuição, que é surpreendentemente fácil de errar, geralmente resultando em falhas bizarras no tempo de execução.
CONTUDO , na programação C ++ diária real, é muito raro escrever uma classe que gerencia sua própria memória; portanto, é enganoso dizer que os programadores de C ++ sempre precisam ser "cuidadosos" para evitar essas armadilhas. Normalmente, você estará fazendo algo mais como:
class Foo
{
public:
Foo(const std::string& s)
: m_first_name(s)
{ }
private:
std::string m_first_name;
};
Essa classe é bem parecida com o que você faria em Java ou C # - não requer gerenciamento explícito de memória (porque a classe da biblioteca std::stringcuida de tudo isso automaticamente), e nenhum material da "Regra de 3" é necessário desde o padrão O construtor de cópias e o operador de atribuição estão bem.
É somente quando você tenta fazer 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;
};
Nesse caso, pode ser complicado para os novatos obterem o construtor de atribuição, destruidor e cópia correto. Mas, na maioria dos casos, não há razão para fazer isso. O C ++ facilita muito evitar o gerenciamento manual de memória em 99% do tempo, usando classes de biblioteca comostd::string e std::vector.
Outro problema relacionado é o gerenciamento manual de memória de uma maneira que não leva em consideração a possibilidade de uma exceção ser lançada. Gostar:
char* s = new char[100];
some_function_which_may_throw();
/* ... */
delete[] s;
Se some_function_which_may_throw()realmente não lançar uma exceção, você é deixado com um vazamento de memória porque a memória alocada paras nunca mais ser recuperado. Mas, novamente, na prática, isso não é mais um problema pela mesma razão que a "Regra de 3" não é mais um problema. É muito raro (e geralmente desnecessário) gerenciar realmente sua própria memória com ponteiros brutos. Para evitar o problema acima, tudo o que você precisa fazer é usar um std::stringou std::vector, e o destruidor será automaticamente chamado durante o desenrolamento da pilha após a exceção ser lançada.
Portanto, um tema geral aqui é que muitos recursos do C ++ que eram não herdados do C, como inicialização / destruição automática, construtores de cópias e exceções, forçam o programador a ter um cuidado extra ao executar o gerenciamento manual de memória no C ++. Porém, novamente, isso é apenas um problema se você planeja gerenciar manualmente a memória, o que quase nunca é mais necessário quando você possui contêineres padrão e indicadores inteligentes.
Portanto, na minha opinião, enquanto o C ++ oferece muita corda extra, quase nunca é necessário usá-lo para se enforcar, e as armadilhas sobre as quais Joel estava falando são trivialmente fáceis de evitar no C ++ moderno.
Your questions should be reasonably scoped. If you can imagine an entire book that answers your question, you’re asking too much.. Eu acredito que isso se qualifica como uma pergunta ... #