Если я укажу значение по умолчанию для аргумента типа "std::string &" в С++, может ли это вызвать утечку памяти?
У меня есть метод, объявленный так:
/*!
\brief Removes the leading and trailing white space from a string.
\param s The string to remove the white space from.
\param white_chars Characters to be considered as whitespace.
*/
std::string Trim(const std::string &s, const std::string &white_chars = " \t\n\r");
Определение метода неинтересно, но здесь оно в любом случае:
std::string Trim(const std::string &s, const std::string &white_chars)
{
size_t startidx = s.find_first_not_of(white_chars);
if (startidx == std::string::npos) return "";
size_t endidx = s.find_last_not_of(white_chars);
return s.substr(startidx, endidx - startidx + 1);
}
Теперь в большинстве случаев использования этого метода я предоставляю только первый аргумент. Valgrind дает мне следующее предупреждение
==3338== 68 bytes in 2 blocks are possibly lost in loss record 4,639 of 7,212
==3338== at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3338== by 0x728CA88: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
==3338== by 0x728E2B4: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
==3338== by 0x728E414: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&, unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
==3338== by 0x728E441: std::string::substr(unsigned long, unsigned long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
==3338== by 0x6965F0A: str::Trim(std::string const&, std::string const&) (appbase.cpp:90)
==3338== by 0x5F481D7: netopt::Element::set_ID(std::string const&) (netopt_elem.cpp:85)
Заметки "блоки, возможно, потеряны"? Я видел утечки памяти, где Valgrind сообщает мне, что "блоки определенно потеряны", но это менее определенное сообщение.
Итак, вопрос возникает, я вызываю утечку памяти, назначая значение по умолчанию std::string &
? Если да, то что я делаю неправильно?
Ответы
Ответ 1
Нет технической проблемы, но философское создание временного std::string
при каждом вызове не так приятно. Особенно с libstdС++ (который вы используете), поскольку он каждый раз вызывает выделение памяти (отсутствие оптимизации коротких строк).
Так как find_first_not_of
имеет перегрузку с использованием char const*
, лучше было бы обеспечить две перегрузки:
// First, the one with the default argument, but without a temporary
std::string Trim(std::string const& s, char const* white_chars = " \t\n\r");
// Second, for convenience, one with a `std::string`
std::string Trim(std::string const& s, std::string const& white_chars);
Это также означает, что при вызове Trim(xx, "abc")
вы избежите создания временного std::string
:)
Конечно, решение overkill заключается в повторном использовании уже написанного кода: Boost String Algorithm имеет множество алгоритмов для строковых манипуляций, включая trim
.
Ответ 2
Нет проблем.
Временная строка создается при каждом вызове и автоматически уничтожается в конце инструкции. Пока вы не сохраняете ссылку на него, нет проблем.
Ответ 3
В общем, только новый /malloc без удаления/освобождения вызовет утечку памяти. В вашем случае нет новых вызовов, поэтому утечка памяти не должна.
" \t\n\r"
находится в стеке памяти и каждый раз используется для создания экземпляра для std::string &white_chars
Временный экземпляр, созданный в стеке и освобождаемый после возврата функции. утечки памяти тоже нет.