If I specify a default value for an argument of type "std::string &" in C++, could that cause a memory leak?
c++, memory-leaks, stdstring, valgrind
Solution
There is no technical issue, but philosophically creating a temporary `std::string` at each call is not so nice. Especially with libstdc++ (which you appear to use) since it causes a memory allocation each time (lack of Short String Optimization).
Since `find_first_not_of` has an overload taking a `char const*`, it would be better to provide two overloads instead:
// 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);
This also means that when calling `Trim(xx, "abc")` you will avoid the temporary `std::string` being generated :)
Of course, the overkill solution is to reuse already written code: Boost String Algorithm has many algorithms for string manipulation, including `trim`.
Problem
I have a method declared like so: ``` /*! \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"); ``` The definition of the method is uninteresting, but here it is anyway: ``` 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); } ``` Now in most usages of this method, I supply just the first argument. Valgrind gives me the following warning ``` ==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) ``` Note "blocks are possibly lost"? I've seen memory leaks where Valgrind tells me "blocks are definitely lost", but this is a less certain message. So the question becomes, am I causing a memory leak by assigning a default value to an `std::string &`? If so, what am I doing wrong?