char * vs std :: string em c ++

Quando devo usar std::string e quando devo usar char* para gerenciar matrizes de char em C ++?

Parece que você deve usar char* se o desempenho (velocidade) é crucial e você está disposto a aceitar alguns negócios arriscados por causa do gerenciamento de memory.

Existem outros cenários a serem considerados?

Você pode passar std :: strings por referência, se eles são grandes para evitar a cópia, ou um ponteiro para a instância, então eu não vejo nenhuma vantagem real usando pointers de char.

Eu uso std :: string / wstring para mais ou menos tudo o que é texto real. char * é útil para outros tipos de dados e você pode ter certeza de que ele será desalocado como deveria. Caso contrário, std :: vector é o caminho a percorrer.

Provavelmente há exceções para tudo isso.

Meu ponto de vista é:

  • Nunca use char * se você não chamar o código “C”.
  • Sempre use std :: string: É mais fácil, é mais amigável, é otimizado, é padrão, impede que você tenha bugs, foi verificado e comprovado que funciona.

Uso de cordas cruas

Sim, às vezes você realmente pode fazer isso. Ao usar const char *, matrizes de caracteres alocadas na pilha e literais de string, você pode fazer isso de forma que não haja alocação de memory.

Escrever esse código requer muitas vezes mais pensamento e cuidado do que usar cadeia de caracteres ou vetor, mas com técnicas adequadas isso pode ser feito. Com as técnicas adequadas, o código pode ser seguro, mas você sempre precisa ter certeza de que, ao copiar para o char [], você tem algumas garantias quanto ao tamanho da string que está sendo copiada, ou você verifica e manipula cordas superdimensionadas graciosamente. Não fazê-lo é o que dava à família de funções, a reputação de ser inseguro.

Como os modelos podem ajudar a escrever buffers de caracteres seguros

Quanto à segurança dos buffers char [], os modelos podem ajudar, pois eles podem criar um encapsulamento para manipular o tamanho do buffer para você. Modelos como este são implementados, por exemplo, pela Microsoft para fornecer substitutos seguros para o strcpy. O exemplo aqui é extraído do meu próprio código, o código real tem muito mais methods, mas isso deve ser suficiente para transmitir a idéia básica:

 template  class BString { char _data[Size]; public: BString() { _data[0]=0; // note: last character will always stay zero // if not, overflow occurred // all constructors should contain last element initialization // so that it can be verified during destruction _data[Size-1]=0; } const BString &operator = (const char *src) { strncpy(_data,src,Size-1); return *this; } operator const char *() const {return _data;} }; //! overloads that make conversion of C code easier template  inline const BString & strcpy(BString &dst, const char *src) { return dst = src; } 

Você deve considerar usar char* nos seguintes casos:

  • Esta matriz será passada no parâmetro.
  • Você sabe antecipadamente o tamanho máximo de sua matriz (você sabe disso ou você impõe).
  • Você não fará nenhuma transformação nessa matriz.

Na verdade, em C ++, char* geralmente são usados ​​para palavras pequenas fixas, como opções, nome de arquivo, etc …

Uma ocasião em que você DEVE usar char* e não std::string é quando você precisa de constantes de string estáticas. A razão para isso é que você não tem nenhum controle sobre os módulos de pedido inicializar suas variables ​​estáticas, e outro object global de um módulo diferente pode se referir a sua seqüência de caracteres antes de ser inicializado. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables

std::string :

  • gerencia a memory para você (a string pode crescer, e a implementação alocará um buffer maior)
  • Interface de programação de nível superior, funciona bem com o resto do STL.

std::string contras: – duas instâncias de strings STL distintas não podem compartilhar o mesmo buffer subjacente. Então, se você passar por valor, você sempre terá uma nova cópia. – Há alguma penalidade de desempenho, mas eu diria que, a menos que suas exigências sejam especiais, é insignificante.

Quando usar um c ++ std :: string:

  • strings, em geral, são mais seguras do que char *, normalmente quando você está fazendo coisas com char * você tem que verificar as coisas para ter certeza de que as coisas estão certas, na class string tudo isso é feito para você.
  • Normalmente, quando se usa char *, você terá que liberar a memory que alocou, você não precisa fazer isso com a string, pois ela liberará seu buffer interno quando for destruída.
  • Strings funcionam bem com stringstream c ++, o IO formatado é muito fácil.

Quando usar char *

  • Usar char * lhe dá mais controle sobre o que está acontecendo “por trás” das cenas, o que significa que você pode ajustar o desempenho se precisar.

Use (const) char * como parâmetros se você estiver escrevendo uma biblioteca. Implementações std :: string diferem entre diferentes compiladores.

Se você quiser usar bibliotecas C, você terá que lidar com cadeias C. O mesmo se aplica se você quiser expor sua API a C.

Você pode esperar que a maioria das operações em um std :: string (como, por exemplo, find ) seja o mais otimizada possível, então é provável que elas executem pelo menos tão bem quanto uma contraparte C pura.

Também vale a pena notar que os iteradores std :: string frequentemente mapeiam para pointers no array char subjacente. Portanto, qualquer algoritmo que você crie sobre iteradores é essencialmente idêntico ao mesmo algoritmo em cima de char * em termos de desempenho.

As coisas a observar são, por exemplo, operator[] – a maioria das implementações STL não executa a verificação de limites e deve traduzir isso para a mesma operação na matriz de caracteres subjacente. O AFAIK STLPort pode, opcionalmente, executar a verificação de limites, ponto em que esse operador seria um pouco mais lento.

Então, o que faz usando std :: string você ganha? Ele te absolve do gerenciamento de memory manual; resize o array torna-se mais fácil e você geralmente precisa pensar menos em liberar memory.

Se você está preocupado com o desempenho ao resize uma string, há uma function de reserve que pode ser útil.

se você estiver usando a matriz de caracteres em texto similar, etc. use std :: string mais flexível e fácil de usar. Se você usá-lo para outra coisa como armazenamento de dados? usar matrizes (preferir vetores)

Mesmo quando o desempenho é crucial, é melhor usar o vector – ele permite a alocação de memory com antecedência (método reserve ()) e ajudará a evitar vazamentos de memory. Usar vector :: operator [] leva a uma sobrecarga, mas você sempre pode extrair o endereço do buffer e indexá-lo exatamente como se fosse um caractere *.

AFAIK internamente, a maioria dos std :: string implementa a cópia na semântica contada, de referência, para evitar sobrecarga, mesmo se as cadeias de caracteres não forem passadas por referência.