Хранение объектов в векторе STL - минимальный набор методов - PullRequest
6 голосов
/ 23 марта 2010

Что такое «минимальный каркас» (необходимые методы) сложного объекта (с явно искаженными внутренними данными), который я хочу сохранить в контейнере STL, например <vector>

Для моих предположений (пример сложного объекта 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

и в Вальгринде:

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

UPDATE:

Минимальные методы для такого объекта: (на основе ответа 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); }
};

Спасибо, sbi, https://stackoverflow.com/users/140719/sbi

Ответы [ 3 ]

10 голосов
/ 23 марта 2010

Обратите внимание, что Чарльз отлично ответил на ваш вопрос .

В любом случае, согласно правилу трех , ваш класс, имеющий деструктор, должен иметь конструктор копирования и оператор присваивания.

Вот как бы я это сделал:

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;}
};
6 голосов
/ 23 марта 2010

Все используемые вами типы должны быть CopyConstructible и Assignable.

CopyConstructible для типа T означает, что если t является T или const T, то выражение T(t) должно выдавать T, эквивалентный исходному t; t. ~ T () должен быть действительным (доступный деструктор); и &t должен дать адрес t как [const] T*.

Assignable означает, что для T, t и T значения u выражение t = u должно сделать t эквивалентным u и иметь тип T&.

Обратите внимание, что все эти требования удовлетворяются простыми встроенными типами и структурами POD. Если вы делаете что-то нетривиальное в деструкторе или конструкторе, вы должны убедиться, что конструктор копирования и оператор присваивания копии сохраняют семантику эквивалентности.

0 голосов
/ 23 марта 2010

Все vector требует, чтобы объект был «присваиваемым», что означает, что ему нужен конструктор копирования, деструктор и оператор присваивания, которые все генерируются по умолчанию, если вы сами их не предоставляете. *

Как говорит sbi, если вам нужна одна из этих функций, то, вероятно, вам нужны все. В вашем случае вам также потребуется предоставить конструктор копирования и оператор присваивания, чтобы избежать повреждения кучи.

...