2015-12-30 7 views
6

У меня есть unordered_set символьногоЭффективное построение станд :: строка из станд :: unordered_set <char>

std::unordered_set<char> u_setAlphabet; 

Тогда я хочу, чтобы получить содержание от множества как станд :: строка. Моя реализация теперь выглядит так:

std::string getAlphabet() { 
    std::string strAlphabet; 
    for (const char& character : u_setAlphabet) 
     strAlphabet += character; 
    return strAlphabet; 
} 

Это хороший способ решить эту задачу? Добавление символов строки в строку кажется не оптимальным для большого u_setAlphabet (несколько reallocs?). Есть ли какой-нибудь другой метод?

+1

В отношении этикета: идентификатор в куске минимального, типичного примерного кода, вероятно, не должен быть неудобно неудобным, как 'u_setAlphabet'. Хорошими идентификаторами, например, являются 'foo',' bar' и 'x'. –

+1

@KerrekSB С другой стороны, я должен сказать, что я предпочитаю код, который копирует неупорядоченный набор 'setAlphabet' в строку' strAlphabet', к той, которая копирует set (или была строка?) 'Foo' в строку (или была установлена ?) 'bar'. – Angew

+0

@KerrekSB хороший пункт, я имею в виду вашу рекомендацию по следующему вопросу. Некоторые ответы, используя эти имена сейчас, поэтому я не буду изменять содержание вопроса здесь – saleph

ответ

12

Самый простой, самый читаемый и самый эффективный ответ:

return std:string(s.begin(), s.end()); 

Реализация может выбрать для определения длины диапазона вверх-вперед и только один раз выделить; как libC++, так и libstdC++ делают это при задании диапазона итераторов в прямом направлении.

string класс также предлагает reserve, так же, как vector, управлять мощность:

std::string result 
result.reserve(s.size()); 
for (unsigned char c : s) result.push_back(c); // or std::copy 
return result; 

Он также предлагает assign, append и insert функций-членов, но так как те предлагают большую гарантию исключения, они могут необходимо выделить новый буфер, прежде чем уничтожить старый (спасибо @TC за то, что он указал на эту важную деталь!). Реализация libC++ не перераспределяется, если достаточна существующая емкость, а реализация libstdC++ GCC5 безоговорочно перераспределяется.

+0

ух, резерв, я забыл об этом :) Но не конструктор std :: string оптимизирует это сам? – saleph

+2

Я бы пересчитал код 'reserve()' только в том случае, если вы знаете, что вы действительно находитесь в критическом для производительности коде, и вы нашли разницу, измерив его. Он убирает ваш код, но если выигрыш оправдывает его, все в порядке. Хорошая стандартная реализация библиотеки зарезервирует память только один раз, даже если конструктор принимает итераторы. Единственное накладное расходы, которое вы получите, это обход, чтобы найти размер спереди. –

+3

@saleph Нет, поскольку 'std :: set :: iterator' только удовлетворяет двунаправленному Итератору' std :: distance' является поэтому операцией O (N). Однако 'std :: set :: size' - операция с постоянным временем. – Daniel

10

Лучше использовать конструктор, который acepts итераторы. Например

std::string getAlphabet() { 
    return { u_setAlphabet.begin(), u_setAlphabet.end() }; 
} 
+0

это много в стиле C++ 11 :) Но что вы думаете (по-вашему) о различиях в удобочитаемости между вашим и @xtofl aswer? Правильно - ваша реализация является самой короткой, но на первый взгляд она выглядит как какая-то магия :) – saleph

+1

@saleph Если C++ выглядит для вас волшебством, тогда вы должны изучить C++ :) Что касается сравнения, то 1) ответ xtofl также записывается с использованием функций C++ 11 и 2) это не соответствует вопросу о том, где сказано об определении функции. –

+0

Конечно, я понимаю ваш код :) Но разве ваша реализация очень похожа на @KerrecSB? Он строит строку, которая, несомненно, будет перенесена позже (например, 'std :: string foo (getAlphabet());') – saleph

1

Оба return std::string(u_setAlphabet.begin(), u_setAlphabet.end()); и return { u_setAlphabet.begin(), u_setAlphabet.end(); одинаковы в C++ 11. Я предпочитаю решение @VladfromMoscow, потому что нам не нужно делать какие-либо предположения о возвращаемом типе временного объекта.

+0

, но разве это скрытая конструкция менее ясна, на ваш взгляд? Я действительно начинаю на C++, поэтому мой смысл читаемости не очень впечатлен :) – saleph

 Смежные вопросы

  • Нет связанных вопросов^_^