повторное использование строкового потока без перераспределения

Я пытаюсь понять, как повторно использовать объект stringstream без необходимости перераспределять базовую строку каждый раз, когда я помещаю что-то в поток. Я нашел этот ответ, который заставил меня сделать это:

int main() {

        stringstream ss;
        int x;
        ss << "423";
        ss >> x; // x is now 423

        ss.clear();
        ss.seekg(0);
        ss.seekp(0);

        ss << "1";
        ss >> x; // x is now 123. Instead I want x to be 1.

        std::cout << x << std::endl;
}

К сожалению, это не работает, так как содержимое строки с первого прохода все еще там (после первого прохода строка есть "423"и после второго прохода "123"). Однако, если добавить пространство сразу после второго положить, все , кажется , работать, как это:

int main() {

        stringstream ss;
        int x;
        ss << "423";
        ss >> x; // x is now 423

        ss.clear();
        ss.seekg(0);
        ss.seekp(0);

        ss << "1";
        ss << " "; // add a space right after the desired value
        ss >> x; // x is now 1

        std::cout << x << std::endl;
}

После второго прохождения строка "1 3". Я не очень хорошо знаком с библиотекой ввода-вывода, и я хотел бы знать, безопасен ли этот подход, или если он просто работает в этом тривиальном примере или если есть более эффективные решения. Живой код здесь . Спасибо!

c++,stringstream,

2

Ответов: class LogHelper { public: ~LogHelper() { std::cout << out.str() << " "; } std::ostream &stream() { return out; } private: std::ostringstream out; }; #define LOG() LogHelper().stream() << __FUNCTION__ << "(" << __LINE__ << ")" #define VAR(x) ", " #x "[" << x << "]" class MyAllocator : public std::allocator<char> { public: using base = allocator<value_type>; using base::allocator; value_type* allocate( std::size_t n, const void * hint) { LOG() << VAR(n); return base::allocate(n, hint); } value_type* allocate( std::size_t n ) { LOG() << VAR(n); return base::allocate(n); } void deallocate( value_type* p, std::size_t n ) { LOG() << VAR(n); base::deallocate(p, n); } }; using MySStream = std::basic_stringstream<char, std::char_traits<char>, MyAllocator>; using MyString = std::basic_string<char, std::char_traits<char>, MyAllocator>; int main() { MySStream ss; // (MyString(255, "")); ss.clear(); int x; ss << "423"; ss << " 423"; LOG(); ss << " 423jlfskdfjl jfsd sdfdsfkdf dsfg dsfg dfg dfg dsfg df gdf gdfg dsfg dsfgdsfgds"; LOG(); ss >> x; ss.clear(); ss.str({}); ss.seekg(0); ss.seekp(0); ss << "1"; ss >> x; std::cout << x << std::endl; LOG(); return 0; }


0 принят

Я провел несколько исследований и экспериментов, используя clang с этим кодом:

Тестовый код

main(55)
allocate(34), n[48]
allocate(34), n[96]
deallocate(39), n[48]
main(57)
1
main(70)
deallocate(39), n[96]
allocate(34), n[256]
allocate(34), n[256]
deallocate(39), n[256]
main(55)
main(57)
1
main(70)
deallocate(39), n[256]
std::basic_stringstream

И у меня есть пара результатов

  1. clang и visual ведут себя одинаково, gcc имеет некоторые проблемы с этим кодом.
  2. std::basic_stringstream строковые буферы всегда растут, никогда не сжимаются
  3. std::stringотстой. Вы не можете зарезервировать размер строки или размер буфера, как в случае ss.str({});. Пользовательский распределитель может передаваться только по типу, вы не можете предоставить распределитель по объекту.
  4. Чтобы уменьшить выделение, вы должны установить большую строку при попрошайничестве, тогда до тех пор, пока вы не добьетесь успеха, перераспределение возможностей не произойдет (второй пример).
  5. предоставление пользовательского распределителя не очень помогает, и при добавлении строки результата добавляется код плиты котла. В моих примерах он используется в основном для распределения журналов и освобождения от него.
  6. ss.str({});не вызывают выделения. Здесь небольшая оптимизация строк помогает

Выводы:

  1. вы можете смело сделать так, 1как рекомендовано в ответном ответе SO, и это не приведет к распределению. Здесь небольшая оптимизация строк помогает и тот факт, что
  2. пользовательский распределитель не очень полезен
  3. установка большой фиктивной строки при попрошайничестве довольно эффективна.
  4. поиск альтернативы должен быть лучшим подходом (возможно, повышение - я не тестировал его)
  5. Точка 1и ваш вопрос показывают, что вы не делали никаких измерений, и ваш вопрос основан на личных предположениях.
C ++, stringstream,
Похожие вопросы