C++ std::list использование памяти

103
09 сентября 2021, 04:40

Только начинаю работать с std::list в Arduino (компилятор C++ 11) Нужно положить в std::list класс:

class TTimerData : public Printable  // для возможности прямой печати
{
  public:
  float t1; 
  float t2; 
  uint32_t time_on; 
  char _tt[20]; // для увеличения размера класса
  String str;

  TTimerData(float ptick1_ON,   float ptick2_OFF, uint32_t ptime_on);
  TTimerData( uint32_t ptime_on);
  // операторы нужны для list.sort()
  bool operator >(TTimerData const & a);
  bool operator <(TTimerData const & a);
  size_t printTo(Print& p) const;
};

Хранить в std::list можно двумя способами:

1 способ: хранить указатели на объекты:

typedef std::shared_ptr<TTimerData> TTimerDataPtr    ; 
typedef std::list<TTimerDataPtr> TTimerDataList;

Добавление элемента:

auto new_order = std::make_shared<TTimerData>(0,0,i); 
lst.push_back(new_order);

shared_ptr нужны для автоматического освобождения памяти после удаления элемента из list.

2 способ: хранить сами объекты:

typedef std::list<TTimerData> TListInside;

Добавление:

lst.emplace_back(0,0,i);  // создает объект внутри List и сразу вызывает конструктор TTimerData

ВОПРОС: какой способ хранения объекта в std::list предпочтительнее (ну или более правильный)?

Я провел в эксперимент, положил в list 200 объектов, в обоих случаях после удаления всех объектов из list ESP.getFreeContStack() и ESP.getFreeHeap() показывают значение, бывшее до момента добавления (т.е. утечки памяти нет)

Опасение у меня вызывает второй способ - когда вызывается метод lst.emplace_back(0,0,i); Я не совсем уверен что для выделения места он использует malloc - а не стек. list используется глобально и если память под новый объект выделяется в стеке - то ничего хорошего меня не ждет. Эксперимент правда показал, что malloc в этом случае используется, но полной уверенности у меня нет.

Answer 1

shared_ptr нужны для автоматического освобождения памяти после удаления элемента

std::list в любом случае сам освобождает память, которую занимал элемент, после его удаления. shared_ptr для этого не нужен.

какой способ хранения объекта в std::list предпочтительнее

Если вам не нужны никакие особенности shared_ptr, то лучше его не использовать.

Опасение у меня вызывает второй способ - когда вызывается метод lst.emplace_back(0,0,i); Я не совсем уверен что для выделения места он использует malloc - а не стек

Он никак не может использовать стек, только кучу. (Хотя скорее new, а не malloc.)

Память, которую функция выделяет в стеке, освобождается после выхода из функции. Если бы emplace_back создавала новый объект на стеке, как бы она могла нормально работать? Этот новый объект уничтожался бы сразу после выхода из emplace_back.

Answer 2

Крайне признателен @HolyBlackCat за весьма содержательную дискуссию.

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

Просто указатели на объект хранить в list нельзя - память под выделенные объекты освобождаться не будет. Для хранения указателей в list применяйте либо shared_ptr либо метод, предложенный @HolyBlackCat (требуется свой CustomAllocator + operator delete ) - на мой взгляд весьма большой кусок дополнительного кода.

READ ALSO
Как сделать progress bar?

Как сделать progress bar?

Выполняется сортировка в потокахВ любой момент из переменной last_index я могу узнать сколько отсортированных элементов уже есть

258
Как выводить элементы массива в приоритетном порядке , создавая кучу из массива

Как выводить элементы массива в приоритетном порядке , создавая кучу из массива

Чтобы вытащить элементы из вектора в приоритетном порядке, кроме как сортировать вектор, можно еще превратить его в кучуВот такая простенькая...

76
Как быстро переименовать переменные в VS C++

Как быстро переименовать переменные в VS C++

Допустим, у меня есть много переменных с названием "a", я хочу их все переименовать в "b" во время редактирования кодаКак можно это быстро сделать?

166