Подтвердить что ты не робот

Рекомендуется ли std:: перемещать строку в контейнеры, которые будут перезаписаны?

У меня есть следующий код

std::vector<std::string> lines;
std::string currentLine;

while(std::getline(std::cin, currentLine)) {
  // // option 1
  // lines.push_back(std::move(currentLine));

  // // option 2
  // lines.push_back(currentLine);
}

Я вижу разные затраты для двух

  • Первый подход очистит currentLine, что сделает getline выделение нового буфера для строки. Но вместо этого он будет использовать буфер для вектора.

  • Второй подход сделает getline возможным повторное использование буфера и потребует нового распределения буфера для строки в векторе.

В таких ситуациях есть ли "лучший" способ? Может ли компилятор более эффективно оптимизировать тот или иной подход? Или существуют умные реализации строк, которые делают один вариант более реалистичным, чем другой?

4b9b3361

Ответ 1

Учитывая преобладание оптимизации коротких строк, я предполагаю, что во многих случаях ничто из этого не будет иметь никакого значения вообще - с SSO, переход заканчивается копированием содержащихся данных в любом случае (даже если источник является rvalue, чтобы он был выбран в качестве источника для перемещения).

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

Что касается: "есть лучший способ", я могу подумать хотя бы о нескольких возможностях. Наиболее очевидным было бы отображение карты в файл, затем прохождение через этот буфер, поиск контуров строк и использование emplace_back для создания строк в векторе непосредственно из данных в буфере без промежуточных строк.

У этого есть незначительный недостаток сопоставления памяти, который не является стандартизованным - если вы не можете жить с этим уровнем непереносимости, вы можете прочитать весь файл в буфер вместо сопоставления памяти.

Следующая возможность после этого заключалась бы в создании класса с интерфейсом вроде строки const, который просто поддерживает указатель на данные в большом буфере вместо того, чтобы делать копию (например, CLang использует что-то вроде этого), Это, как правило, уменьшает общее распределение, фрагментацию кучи и т.д., Но если вам (например) необходимо изменить строки после этого, вряд ли это будет иметь много (если таковые имеются).