quinta-feira, 11 de agosto de 2011

3 dicas simples para deixar o código mais eficiente


Aqui vão três dicas de C++ que, apesar de simples, muita gente não se liga quando está desenvolvendo.

  1. Declare variáveis no menor escopo possível

Muitos programadores, principalmente aqueles que vêm do C, tem o costume de declarar todas as variáveis no começo de cada função. Esta prática, apesar de muita gente defender que é interessante por questões de design, acaba prejudicando o desempenho de seu programa.
Observe o seguinte código:

void Funcao( int x )
{
    std::string minhaString(“teste”);
    if ( x > 10 )
    {
        //faz alguma coisa com “minhaString”;
        ...
    }
    else
    {
        printf(“Valor invalido de x”);
    }
}

Note que o objeto minhaString só será utilizado caso x seja maior que 10, porém ele é criado em todas as situações. Se x for menor que 10, minhaString será criado e depois destruído sem ser usado de fato.

Uma função mais eficiente poderia ser escrita da forma:

void Funcao( int x )
{
    if ( x > 10 )
    {
        std::string minhaString(“teste”);
        //faz alguma coisa com “minhaString”;
        ...
    }
    else
    {
        printf(“Valor invalido de x”);
    }
}

Assim, caso x seja menor que 10, minhaString nem ao menos será criada.

  1. Passe objetos como const &

Observe a seguinte função:

void ImprimeVector( std::vector< int > vetor )
{
    for ( int i = 0; i < vetor.size(); ++i )
    {
        printf( "%d ", vetor[i] );
    }
}

E a sua chamada:

std::vector< int > meusNumeros;
//adiciona um monte de elementos em meusNumeros
...
ImprimeVector( meusNumeros );

A função funciona corretamente, porém note que, ao se passar meusNumeros como parâmetro para ImprimeVector, um novo vetor idêntico é criado em memória. Dependendo da quantidade de elementos contidos em meusNumeros, isso pode consumir um tempo e memória razoáveis.

Não seria melhor se pudéssemos utilizar dentro da função o mesmo objeto que foi criado fora?

Isso é simples. Basta que o parâmetro receba a referência de um vector. Para garantir que o nosso objeto não será modificado dentro da função, marcamos o parâmetro como const também. Assim:

void ImprimeVector( const std::vector< int >& vetor )

Tanto a chamada da função quanto a utilização de vetor dentro dela permanecem idênticas.

  1. Evite chamar funções desnecessariamente

Parece óbvio, mas este é um erro bastante comum. Vamos ao exemplo anterior:


for ( int i = 0; i < vetor.size(); ++i )
{
    printf( "%d ", vetor[i] );
}

Note que a função size() do vetor é chamada para cada iteração do for. Isso é desnecessário, já que sabemos que o tamanho não irá variar dentro do loop.
O melhor seria implementar a função da seguinte forma:

int tamanho = vetor.size();
for ( int i = 0; i < tamanho; ++i )
{
    printf( "%d ", vetor[i] );
}

P.s.: Alguns compiladores podem até otimizar a chamada do size() nessas situações, mas isso não é garantido. Por isso, é melhor fazer direito.


É isso aí pessoal. Outro dia posto mais dicas sobre como deixar o código mais eficiente. Até lá!

Nenhum comentário:

Postar um comentário