Pergunta

O que é "estrutura mínima" (métodos necessários) de objeto complexo (com dados internos explicitamente mallocados), que eu quero armazenar no contêiner STL, por exemplo, <vector>?

Para minhas suposições (exemplo de objeto complexo doit):

#include <vector>
#include <cstring>
using namespace std;
class Doit {
    private:
        char *a;
    public:
        Doit(){a=(char*)malloc(10);}
        ~Doit(){free(a);}
};

int main(){
    vector<Doit> v(10);
}

*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0804b008 ***
Aborted

E em Valgrind:

malloc/free: 2 allocs, 12 frees, 50 bytes allocated.

ATUALIZAR:

Os métodos mínimos para esse objeto são: (com base na resposta do SBI)

class DoIt{
    private:
        char *a;
    public:
        DoIt() { a=new char[10]; }
        ~DoIt() { delete[] a; }
        DoIt(const DoIt& rhs) { a=new char[10]; std::copy(rhs.a,rhs.a+10,a); }
        DoIt& operator=(const DoIt& rhs) { DoIt tmp(rhs); swap(tmp); return *this;}
        void swap(DoIt& rhs) { std::swap(a,rhs.a); }
};

Obrigado, SBI, https://stackoverflow.com/users/140719/sbi

Foi útil?

Solução

Observe que Charles tem respondeu sua pergunta perfeitamente.

Enfim, de acordo com o Regra de três, sua turma, tendo um destruidor, deve ter um construtor de cópia e um operador de atribuição também.

Veja como eu faria isso:

class Doit {
    private:
        char *a;
    public:
        Doit()                   : a(new char[10]) {}
        ~Doit()                    {delete[] a;}
        DoIt(const DoIt& rhs)    : a(new char[10]) {std::copy(rhs.a,rhs.a+10,a);}
        void swap(DoIt& rhs)       {std::swap(a,rhs.a);}
        DoIt& operator=(DoIt rhs)  {swap(rhs); return *this;}
};

Outras dicas

Todos os tipos que você usa devem ser CopyConstructible e Assignable.

CopyConstructible para um tipo T significa que se t é um T ou a const T então a expressão T(t) deve produzir um equivalente T para o original t; t. ~ t () deve ser válido (destruidor acessível); e &t deve dar o endereço de t como um [const] T*.

Assignable significa que para um T, t e a T valor u, a expressão t = u deve fazer t equivalente a u e ser do tipo T&.

Observe que todos esses requisitos são atendidos por tipos e estruturas de pod simples. Se você fizer algo não trivial em um destruidor ou construtor, deve garantir que o construtor de cópias e o operador de atribuição de cópia Preserver a semântica da equivalência.

Tudo vector Requer é que o objeto seja "atribuível", o que significa que ele precisa de um operador de cópia, destruidor e atribuição, todos gerados por padrão se você não os fornecer.

Como diz o SBI, se você precisar de uma dessas funções, provavelmente precisa de todas elas. No seu caso, você também precisará fornecer um construtor de cópia e operador de atribuição para evitar a corrupção da pilha.

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