C++. std::vector - не пойму, SFML. куча вопросов

164
09 марта 2018, 15:20

Проясните пожалуйста. То что кладется в std::vector оно размещается в динамической памяти (то есть как при вызове new)? Как вообще поместить объекты в динамическую память в вектор?

Вот например вектор с указателями

std::vector <Obj*> OBJ_Ptrs;

Если я туда понасоздаю их в стиле Obj o("id") и понакладу кучу этих самых Obj*, допустим они большие и сложные сами по себе, то они в динамическую память попадут?

Еще такая проблема с SFML. У меня лежит в векторе указатели на объекты, которые унаследованы от sf::Sprite, у такого объекта переопределен метод draw

void draw(sf::RenderTarget& rt)const  override;
void Obj::draw(sf::RenderTarget & rt) const
{
    rt.draw(*this); 
}

В самом Obj, есть указатели на спрайт, там на текстуру и тп, это все наследуется из спрайта. Когда я манипулирую вектором из этих указателей на Obj, все нормально, а когда получаю элемент вектора, разыменовываю, и у него вызываю draw, то у этого obj (*this) ломаются указатели на текстуру. Это известный факт такой поломки текстуры в sfml, но я не пойму почему так у меня, я все через указатели делаю.

UPD. ну вроде с белыми текстурами разобрался. У меня был некий чужой ресурс-менеджер, в который я добавил функцию по получению тайлов, аналогично той что была, только с расчетом по индексу и размеру вырезкой, ну и поиском сначала большой текстуры в памяти, а не сразу из файла, но почему то перед возвращение шаред-указателя не клал его в мапу c шаред-указателями, так же как оригинальная функция из менеджера. ну и указатель наверное умирал, когда за скобки выходил. До конца механику работы умных ук. не понимаю еще.

Answer 1

std::vector хранит данные в памяти, динамически выделенной аллокатором. Аллокатор по умолчанию выделяет память при помощи operator new(), но можно также, например, выделять память на стеке, или при помощи malloc. Так или иначе, vector получает блок памяти и последовательно размещает в нём объекты, если блока памяти не хватает - запрашивает новый и размещает объекты уже в нём, а старый освобождает.

Таким образом, если вы просто создаёте std::vector<Obj> - вы получаете набор объектов в динамической памяти, при этом все они будут последовательно располагаться в одном блоке памяти. Но при добавлении нового объекта предыдущие объекты могут быть перемещены или копированы в другой блок памяти, что может привести в том числе к повреждению ресурсов. Если вы создаёте std::vector<Obj*> - в динамической памяти будут созданы только указатели, сами объекты созданы не будут, их нужно создавать самостоятельно при помощи new или умных указателей - и эти объекты уже гарантированно будут созданы в динамической памяти и не будут перемещаться при добавлении новых объектов.

Вот пример создания вектора объектов в динамической памяти при помощи умных указателей (вероятно, вам нужно именно это):

class Obj {
  // Для объектов с виртуальными функциями копирование может привести к проблемам. 
  // Возможно, именно из-за незапланированного копирования у вас возникли проблемы
  Obj(const Obj&) = delete; 
  virtual void call(){} 
  virtual ~Obj(){}
};
class Foo: public Obj {
  void call(){}
  ~Foo(){}
};
std::vector<std::uniqie_ptr<Obj>> vector;
vector.emplace_back(std::make_unique<Obj>());
vector.emplace_back(std::make_unique<Foo>());
for(auto&& obj: vector)
   obj->call();
READ ALSO
Является ли нуль-терминатор байтом? [дубликат]

Является ли нуль-терминатор байтом? [дубликат]

На данный вопрос уже ответили:

141
Ошибка. Проблема в коде или в среде?

Ошибка. Проблема в коде или в среде?

Ошибка: maincpp|10|error: expected ')' before 'st'

150
C++ std::string::find неверно работает

C++ std::string::find неверно работает

Нужно распарсить строку, для этого необходимо найти позицию знака

147
Видоизменение имен функциий

Видоизменение имен функциий

Для чего компиляторы C++ "манглят" имена функций

125