Armazenamento de objetos no STL Vector - Conjunto mínimo de métodos
-
21-09-2019 - |
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);
}
dá
*** 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
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.