Храня объекты в векторе STL - минимальный набор методов

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

Для моих предположений (пример Мелкой монеты сложного объекта):

#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

и в valgrind:

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

ОБНОВЛЕНИЕ:

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

6
задан Community 23 May 2017 в 11:47
поделиться

3 ответа

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

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

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

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;}
};
10
ответ дан 8 December 2019 в 14:42
поделиться

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

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

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

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

6
ответ дан 8 December 2019 в 14:42
поделиться

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

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

0
ответ дан 8 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: