Pergunta

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

Parece que você deve usar char* se o desempenho (velocidade) é crucial e que está disposto a aceitar alguma de um negócio arriscado por causa do gerenciamento de memória.

Existem outros cenários a considerar?

Foi útil?

Solução

Você pode passar std :: cordas 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 ponteiros de char.

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

Há provavelmente exceções a tudo isso.

Outras dicas

Meu ponto de vista é:

  • Nunca use char * se você não chamar "C" código.
  • Sempre usar std :: string:. É mais fácil, é mais amigável, é otimizado, é padrão, ele irá impedir que você tenha erros, tem sido verificada e comprovada para o trabalho

Cadeia Uso Raw

Sim, às vezes você realmente pode fazer isso. Ao usar const char *, matrizes de caracteres alocada na pilha e string literais você pode fazê-lo de tal forma que não há alocação de memória em tudo.

Escrevendo tal código requer muitas vezes mais pensamento e cuidado do que usando corda ou vector, mas com técnicas adequadas que pode ser feito. Com técnicas apropriadas o código pode ser seguro, mas você sempre precisa ter certeza de quando copiar para char [] você quer ter algumas garantias sobre o comprimento da corda que está sendo copiado, ou você verificar e lidar com cordas de grandes dimensões graciosamente. Não fazer isso é o que deu à família strcpy de funções a reputação de ser inseguro.

Como modelos podem ajudar a escrever buffers de char seguros

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

template <int Size>
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 <int Size>
inline const BString<Size> & strcpy(BString<Size> &dst, const char *src)
{
  return dst = src;
}

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

pros std::string:

  • administra a memória para você (a cadeia pode crescer, ea implementação irá alocar uma maior buffer de você)
  • interface de programação de alto nível, funciona muito bem com o resto de STL.

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

Você deve considerar usar char* nos seguintes casos:

  • Esta matriz será passado no parâmetro.
  • Você sabe com antecedência o tamanho máximo de sua matriz (você sabe ou você impô-lo).
  • Você não vai fazer qualquer transformação nessa matriz.

Na verdade, em C ++, char* são muitas vezes usam por palavra pequena fixa, como opções, nome do arquivo, etc ...

Quando usar um c ++ std :: string:

  • cordas, em geral, são mais seguros do que char *, Normalmente, quando você está fazendo as coisas com char * você tem que verificar coisas para garantir que as coisas estão bem, na classe string tudo isso é feito para você.
  • Normalmente, quando usando char *, você terá que liberar a memória que você alocado, você não tem que fazer isso com corda, uma vez que irá liberar seu buffer interno quando destruído.
  • Cordas trabalho bem com c ++ stringstream, formatado IO é muito fácil.

Quando usar char *

  • Usando 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 você precisa.

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ê vai ter que lidar com strings C. Mesmo se aplica se você deseja expor sua API para C.

Você pode esperar a maioria das operações em um std :: string (como por exemplo find) a ser tão otimizado quanto possível, de modo que eles estão propensos a realizar, pelo menos, bem como uma contrapartida C puro.

É importante notar também que iterators std :: string muitas vezes mapear para ponteiros na matriz de char subjacente. Assim, qualquer algoritmo que você planejar em cima de iteradores é essencialmente idêntico ao do mesmo algoritmo em cima de char * em termos de desempenho.

As coisas que atente para são por exemplo operator[] - a maioria das implementações STL não executar verificação de limites, e deve traduzir isso para a mesma operação na matriz de caracteres subjacente. AFAIK STLport pode, opcionalmente, realizar verificação de limites, altura em que este operador seria um pouco mais lento.

Então, o que faz usando std :: string ganhar você? Ele absolve-o de gerenciamento de memória manual; redimensionar a matriz se torna mais fácil, e você geralmente tem que pensar menos em liberar memória.

Se você está preocupado com o desempenho ao redimensionar uma corda, há uma função reserve que você pode achar útil.

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

Mesmo quando o desempenho é crucial é melhor uso vector<char> - permite a alocação de memória com antecedência (método de reserva ()) e irá ajudá-lo a evitar vazamentos de memória. Usando vector :: operator [] leva a uma sobrecarga, mas você sempre pode extrair o endereço do buffer e posicioná-lo exatamente como se fosse um char *.

AFAIK internamente mais std :: string implementar cópia na escrita, referência contada semântica para evitar sobrecarga, mesmo cordas não são passados ??por referência.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top