Это продолжение this question. Предположим, что я пишу интерфейс C++, который принимает или возвращает строку const. Я могу использовать константный символ * завершается нулем строку:Как должен выглядеть интерфейс приема строк?
void f(const char* str); // (1)
Другой способ будет использовать зЬй :: строка:
void f(const string& str); // (2)
Также можно написать перегрузку и принять как:
void f(const char* str); // (3)
void f(const string& str);
Или даже шаблон в сочетании с усилением строковых алгоритмов:
template<class Range> void f(const Range& str); // (4)
Мои мысли:
- (1) не C++ иш и могут быть менее эффективными, когда последующие операции необходимо знать длину строки.
- (2) Плохо, потому что теперь
f("long very long C string");
вызывает конструкцию std :: string, которая включает выделение кучи. Еслиf
использует эту строку, чтобы передать ее на какой-то низкоуровневый интерфейс, который ожидает C-строку (например, fopen), то это просто пустая трата ресурсов. - (3) вызывает дублирование кода. Хотя один
f
может вызывать другой в зависимости от того, что является наиболее эффективной реализацией. Однако мы не можем перегружать на основе типа возврата, как в случае std :: exception :: what(), который возвращает const char *. - (4) не работает с отдельной компиляцией и может привести к еще большему раздуванию кода.
- Выбор между (1) и (2), основанный на том, что необходимо для реализации, - это утечка детализации реализации в интерфейс.
Вопрос в следующем: какой предпочтительный способ? Есть ли какая-то одна рекомендация, которой я могу следовать? Каков ваш опыт?
Edit: Существует также пятый вариант:
void f(boost::iterator_range<const char*> str); // (5)
, который имеет плюсы из (1) (не нужно построить объект строки) и (2) (от размера строка явно передается функции).
в случае (2) не будет распределения кучи. строка будет построена в стеке –
@nice: справа, std :: string сама выделяется в стеке. Но если ваша строка достаточно длинная или ваша реализация не использует оптимизацию с короткой строкой, то std :: string будет выделять ее хранилище в куче. – ybungalobill
Я думаю, что распределение кучи произойдет только тогда, когда std :: string copy contructor называется –