Ponto V!

Home C/C++ Smart Pointers Boost Shared Array e Scoped Array (shared_array e scoped_array)
Bruno Crivelari Sanches
Boost Shared Array e Scoped Array (shared_array e scoped_array)Imprimir
Escrito por Bruno Crivelari Sanches

Para ver o tutorial anterior da série: Boost Scoped Pointer

Todo os smart pointers que mostrei até agora tem um problema que ainda não vimos como resolver: eles não funcionam com arrays! Isso acontece pois como todo programador C++ sabe (sabe mesmo não é?) devemos usar o delete[] para liberar a memória de um array, por exemplo:

#include <string>
#include <iostream>

class Person
{
    public:
        inline void SetName(const std::string &name)
        {
            m_Name = name;
        }

        ~Person()
        {
            using namespace std;
            cout << "Fui destruido: " << m_Name << endl;
        }

    private:
        std::string m_Name;
};

int main(int, char **)
{
    Person *p = new Person[10];
    delete []p;

    return(0);
}

Se ao invés do delete[], for usado um delete comum, geralmente a memória é liberada corretamente, mas somente o destrutor do primeiro elemento do array é executado. Isto ocorre porque o delete comum (e o compilador na maioria das vezes) não tem como saber se um ponteiro aponta para um elemento apenas ou para um array. Então precisamos de alguma forma avisar eles sobre o array. Para fazer o teste, coloque um printf no destrutor da classe Person e modifique o exemplo acima para rodar o delete normal.

Mas como o compilador sabe quantos elementos destruir? Isso depende, uma implementação que pode ser usada é toda vez que for alocado um array, alocar antes dele um int e colocar nele o tamanho do array, assim o delete poderia ser implementado +/- assim:

template <typename T>
operator delete[](T *ar)
{
    int num = ((int *)ar)-1;
    for(int i = 0;i < num; ++i)
        ar[i].~T();

    free(ar);
}

Alguns compiladores usam técnicas semelhantes a esta, mas não existe nenhuma garantia sobre qual a técnica a ser utilizada, isso depende da implementação. Agora porque não incluir em todos os ponteiros alocados um int com a quantidade de objetos? Bom, simplesmente porque senão toda a alocação teria esse ônus de um int a mais (acredito que devam existir outros problemas, mas isso não vem ao caso), que poderia atrapalhar a vida de alguns programas, dessa forma, seguindo a filosofia do C++ “Você não paga pelo o que não usa” temos como resultado dois operadores de delete.

Smart Pointers e Arrays

Para contornar esse problema das arrays, a boost criou então o shared_array, que é usado especificamente para arrays. Seu uso é quase o mesmo do shared_ptr:

#include <boost/shared_array.hpp>
#include <string>

int main(int, char **)
{
    const int NUM = 10;
    boost::shared_array<Person> p(new Person[NUM]);

    using namespace std;
    for(int i = 0;i < NUM; ++i)
        p[i].SetName(string("Bruno"));
    
    return(0);
}

Não tem segredo! Existe um outro smart pointer para arrays, o scoped_array, que tem comportamento idêntico ao scoped_ptr, mas pode ser usado com arrays:

#include <boost/scoped_array.hpp>
#include <string>

int main(int, char **)
{
    const int NUM = 10;
    boost::scoped_array<Person> p(new Person[NUM]);
    
    using namespace std;
    for(int i = 0;i < NUM; ++i)
        p[i].SetName(string("bcs"));

    return(0);
}

Novamente não mudou quase nada no código, apenas o nome do smart pointer usado. Mas lembre-se que nos bastidores tivemos algumas mudanças, pois o shared_array precisa assim como o shared_ptr alocar um objeto para contagem de referencia, já o scoped_array (da mesma forma que o scoped_ptr) não precisa de nada disso.

No próximo tutorial, vamos ver a ultima classe de smart pointer da Boost, o intrusive_ptr.

Próximo tutorial da série: Boost Intrusive Pointer


Comentários (2)
  • Pedro Silva Moreira - PeJuGe  - Aplicação
    avatar

    Devo confessar que por pura ignorância, na criação de um jogo, relativamente grande, eu não usei ponteiros inteligentes, o que resultou em alocação de memória indevida.
    Criando duas telas por exemplo, como o corpo foi ficando muito grande e não cuidei disso quando estava projetando a memória continuava alocada, ou seja...
    Cada vez fico mais adepto à boost, mesmo não programando tanto tempo em C++, fica sempre a vontade :P.
    Muito bom tutorial.

  • Bruno Crivelari Sanches
    avatar

    Valeu Pedro!

    A boost ajuda bastante, apesar da documentação não ser lá essas coisas, economiza um bom tempo!

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter