#c #vector #sfml #stdvector
Вопрос:
Я создаю графическое приложение, используя библиотеку SFML. У меня есть класс Square
, который создает квадратный блок с буквой внутри. У этого класса есть члены sf:: Font
и sf::Text
, за исключением самого квадрата ( sf::RectangleShape
). Конструктор этого класса принимает размер стороны квадрата, его положение, путь к шрифту, расположенному в папке проекта, и букву, на которую будет записано sf:: Text
. Класс также содержит draw()
метод, который берет объект sf::RenderWindow
типа и рисует сам квадрат и текст, используя его.
Вот в чем проблема. Когда я создаю несколько экземпляров площади (и, соответственно, письмо с ним) с использованием отдельных переменных, все работает нормально, но когда я пытаюсь push_back площадях std::vector
, все ломается, ошибки вылетают в режиме отладки и в режиме релиза только маленькие точки взяты вместо букв и программа не работает правильно, окно может перестать отвечать на запросы (только квадраты без письма работать с std::vector
и их тянет нормально)
Я думаю, что есть ошибки, связанные с динамической памятью, указателями или итераторами, но я сам не могу разобраться и понять, что происходит, заранее благодарю вас за помощь.
Код для лучшего понимания:
class Square
{
public:
RectangleShape m_square;
Font m_font;
Text m_text;
Square(int size, Vector2f pos, string fontPath, string letter)
{
m_square.setFillColor(Color(0, 0, 0, 50));
m_square.setSize(Vector2f(size, size));
m_square.setPosition(pos);
if (!m_font.loadFromFile(fontPath))
wcout << "Error loading the font!" << endl;
m_text.setFont(m_font);
m_text.setFillColor(Color(0, 0, 0, 220));
m_text.setCharacterSize(size * 0.8);
m_text.setString(letter);
m_text.setPosition(Vector2f((pos.x - m_text.getGlobalBounds().left) (size - m_text.getGlobalBounds().width) / 2, pos.y));
}
void draw(RenderWindowamp; window)
{
window.draw(m_square);
window.draw(m_text);
}
};
main.cpp:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <vector>
#include <string>
#include "Square.h"
using namespace sf;
using namespace std;
int main()
{
ContextSettings settings;
settings.antialiasingLevel = 10;
RenderWindow window(VideoMode(1200, 800), "My window", Style::Default, settings);
window.setVerticalSyncEnabled(true);
Square sq1(50, Vector2f(100, 100), "Roboto-Bold.ttf", "A");
Square sq2(50, Vector2f(200, 100), "Roboto-Bold.ttf", "B");
Square sq3(50, Vector2f(100, 200), "Roboto-Bold.ttf", "C");
Square sq4(50, Vector2f(200, 200), "Roboto-Bold.ttf", "D");
vector<Square> squares;
squares.push_back(Square(50, Vector2f(400, 100), "Roboto-Bold.ttf", "A"));
squares.push_back(Square(50, Vector2f(500, 100), "Roboto-Bold.ttf", "B"));
squares.push_back(Square(50, Vector2f(400, 200), "Roboto-Bold.ttf", "C"));
squares.push_back(Square(50, Vector2f(500, 200), "Roboto-Bold.ttf", "D"));
while (window.isOpen())
{
window.clear(Color::White);
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
{
window.close();
}
}
sq1.draw(window);
sq2.draw(window);
sq3.draw(window);
sq4.draw(window);
for (autoamp; s : squares)
{
s.draw(window);
}
window.display();
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
window.close();
}
}
}
Вот скриншот окна программы
Любая помощь будет признательна.
Комментарии:
1.Начните читать документацию перед написанием кода.. Text::setFont Аргумент шрифта ссылается на шрифт, который должен существовать до тех пор, пока текст его использует. Действительно, текст не хранит свою собственную копию шрифта, а скорее сохраняет указатель на тот, который вы передали этой функции. Если шрифт уничтожен и текст пытается его использовать, поведение не определено. у вас висит ссылка на шрифт из — за его неглубокого копирования-выполняется операция копирования по умолчанию
Square
.2. Используйте интеллектуальные указатели, чтобы сохранить все ваши объекты — чтобы избежать их неглубокого копирования или обеспечить правильные операции, такие как конструкторы копирования/перемещения и операторы присваивания.
Ответ №1:
В качестве простого обходного пути и небольшого улучшения памяти и производительности рассмотрите возможность хранения ваших шрифтов в std::map<std::string, sf::Font>
папке. Эта структура данных позволяет сопоставлять имя шрифта с объектом, и она обладает тем приятным свойством, что объекты в ней не перемещаются при добавлении новых.
// add this at top level
std::map<std::string, sf::Font> fonts;
// Change the Square constructor as such:
Square(int size, Vector2f pos, string fontPath, string letter) {
if (auto it = fonts.find(fontPath); it == fonts.cend()) {
// Font was not created before.
autoamp; font = fonts[fontPath]; // this access will create a Font object and automatically store it in the map
if (!font.loadFromFile(fontPath))
wcout << "Error loading the font!" << endl;
}
...
m_text.setFont(fonts[fontPath]);
...
}
и, конечно же, избавиться от m_font
члена.