Как быстро скопировать содержимое std :: string?

я прочитал немного связанные с вопросы, но ничего о скорости сравнения memcpyа также strncpy,

Что вы рекомендуете отслеживать содержимое строки в критическом разделе?

  • избегать динамического выделения памяти
  • элегантность кода и читаемость / понятность (несколько строк кода)
  • быстрая обработка (мало инструкций, предотвращение промахов)
  • возможность оптимизации с помощью компилятора (или с реализациями, уже использующими оптимизированные инструкции)

Я думал о функции:

  1. memcpy требуется рассчитать минимальную длину (см. фрагмент coliru.stacked-crooked.com)

    void copy (char dst[20], const std::string& src)
    {
    if (src.size() < sizeof(dst)) {
    memcpy (dst, src.c_str(), src.size()+1);
    } else {
    memcpy (dst, src.data(), sizeof(dst)-1);
    dst[sizeof(dst)-1] = 0;
    }
    }
    
  2. strncpy поиск завершает нулевой байт, а ненужный заполняет все последние байты (см. отрывок)

    void copy (const std::string src, char (*dst)[20])
    {
    strncpy (dst, src.c_str(), sizeof(dst)-1);
    dst[sizeof(dst)-1] = 0;
    }
    
  3. snprintf?

  4. std::string::copy как предложено DYPкомментарий …

  5. std::copy как снова предложено тем же DYPкомментарий …

  6. любая другая идея?

Тесты могут быть выполнены, но они должны основываться на нескольких компиляторах / версиях, разных наборах флагов и различном оборудовании / ОС. Я бы предпочел ответы на основе ваших отзывов / опыта / опыта или математических знаний …

Поскольку это общий вопрос, люди, которые ищут одни и те же вопросы, оценят общий ответ, а не мой конкретный текущий случай.

Для вашей информации, один поток требует записи в файл несколько std::string что их содержание может быть изменено другим потоком. Я не могу изменить этот другой поток, и этот другой поток очень занят. Если я не блокирую (mutex / spinlock) копию строки, у меня иногда возникают некоторые проблемы. Поэтому я хочу быстро скопировать эти std::string и напишите их после раздела блокировки.

1

Решение

Прежде всего, я не могу сказать, какая версия быстрее. Как вы, вероятно, знаете, это сильно зависит от вашего компилятора, системы, реализации и т. Д.

Если вы знаете размер заранее (у вас есть std::string а также size() принимает O(1)), это наверное быстрее использовать memcpy так как у него меньше дел (только копии, без сравнений). Вы можете написать это так:

void copy(char* buffer, std::size_t buffersize, const std::string& str)
{
std::size_t len = std::min(buffersize-1, str.size());
memcpy(buffer, &str[0], len); // using &str[0] instead of data()
buffer[len] = '\0';
}

Но я бы никому об этом не поверил. Правильнее всего протестировать все варианты, которые у вас есть, и выбрать конкретный сценарий (о котором я ничего не знаю).


Мой конкретный случай, чтобы быстро хранить некоторые std::string в критической секции (спин-блокировка) и после этого сбрасывать эти строки. Поэтому я хочу предотвратить динамическое выделение памяти.

Чего я не понял, так это почему не пользуюсь std::string, Если вы хотите предотвратить распределение, вы можете reserve() немного памяти для вашей строки (столько же, сколько будет у вас в массиве char). Или вы можете взять константную ссылку на строку и использовать ее в критическом разделе. Распределение не будет.

3

Другие решения

Когда вы используете c_str () вместо data (), вы рискуете, что std :: string создаст временную копию для присоединения завершающего 0. И когда вы используете data (), вы не можете использовать stncpy.

Не знаю, есть ли много реализаций, которые действительно делают эту временную копию. Потеря байта для терминатора не такая уж большая проблема. Но:

  • В чистом коде C ++ вам никогда не нужен c_str (), так зачем его оптимизировать?
  • Это не только один байт впустую, это также время, необходимое для его поддержания
  • Некоторые реализации избегают выделения дополнительной динамической памяти для очень коротких строк.
    Там, будучи в состоянии хранить один байт более или менее важно.
  • Может быть, реализация выполняет оптимизацию копирования при записи для операций с подстрокой?
0

По вопросам рекламы [email protected]