Оптимизация работы с памятью в С++

120
20 августа 2019, 09:20

решил написать свой .obj парсер, и столкнулся с небольшой проблемой...

...
std::vector<Math::Vector4<float>> vertices;
std::string line;
std::ifstream inputStream(objFileName);
while (std::getline(inputStream, line))
{
    if (line.substr(0, 2) == "v ")
    {
        std::istringstream stream(line.substr(2));
        float x, y, z;
        stream >> x;
        stream >> y;
        stream >> z;
        vertices.push_back({ x, y, z, 1.0f });
    }
    ... // Texture coordinate, normals e.t.c.
}

Вопрос заключается в следующем, можно ли как-то оптимизировать в данном случае работу с памятью, но так сказать не во вред удобности? При substr постоянно же будет аллоцироваться новая строка, да и при создании стрима. Хотелось бы как-то ограничиться парой выделений памяти и все на этом, а не фрагментировать кучу такими маленькими выделениями(вектор в дальнейшем будет заменен, так как тоже очень затратно будет происходить реаллоцирование памяти, пока просто хотел бы разобраться со строками)...

Answer 1

В современном С++ всю работу с константными/немодифиуируемыми [под]строками имеет смысл переводить на использование std::string_view. То есть везде, где в вашей программе явно или концептуально выступает const std::string & он должен быть заменен на const std::string_view &. Это относится и к вашему применению substr. Нет никаких причин формировать целый новый std::string объект только ради выделения немодифицируемой подстроки.

По уму и std::string::substr должен был бы возвращать std::string_view, а не std::string, но так исторически сложилось и сейчас уже не переделать.

В данном случае можно предложить заменить все

line.substr(i, j) 

на

std::string_view(line).substr(i, j)

Это избавит вас от ненужных промежуточных std::string объектов и сопутствующего выделения памяти.

Или уже с самого начала вы могли после получения line сразу сформировать

std::string_view line_view = line;

и дальше работать исключительно с line_view.

Это, однако, не избавит вас от выделения памяти при инициализации std::istringstream и внутри std::istringstream. Здесь бы бы полезен парсер для std::string_view, но готового в стандартной библиотеке нет (кроме sscanf). Сама стандартная библиотека еще толком не перешла на использование std::string_view.

Ваше

vertices.push_back({ x, y, z, 1.0f });

это тоже потенциально - ненужное копирование. Возможно, что лучше

vertices.emplace_back(x, y, z, 1.0);

но это уже зависит от свойств Math::Vector4<float>.

READ ALSO
Работа заголовочных файлов

Работа заголовочных файлов

Возможно вопрос покажется глупым, но я новичок в работе с С++

104
Минимальный размер QWidget с учетом содержимого

Минимальный размер QWidget с учетом содержимого

Мне необходимо чтобы виджет занимал минимально возможное пространство, но с учетом того, что он не может быть меньше, чем его содержимоеЕго...

96