I'm new to C++, and I have been playing around with its standard regex library. I made this proof of concept search function based on the following reference.
https://en.cppreference.com/w/cpp/regex/regex_iterator
This code compiles fine and runs as expected, but looking in retrospect, there are a couple of spots I'm worried about that might be causing some memory leak.
How do you handle a string return value from a library call? Do you copy them to your own string object that's created by new
? Or do you treat them like values and never worry about memory allocation?
I know make_unique
and make_shared
are great options to look into, but I am not comfortable using them while my understanding of c++ memory management structure (like where destructor is called etc) is still shaky.
#include <iostream>
#include <string>
#include <regex>
#include <vector>
//a proof of concept function that returns regex match strings
std::vector<std::string> return_matches(std::string str){
std::regex reg("[0-9]+");
std::vector<std::string> result;
auto i = std::sregex_iterator(str.begin(), str.end(), reg);
auto str_end = std::sregex_iterator();
for(i; i != str_end; ++i ){
std::smatch match = *i;
result.push_back(match.str());
//string returned from match.str() will be shallow copied into the result array
//but at the same time, the string seems like to be going out of the scope,
//does that mean its destructor is called and its internal (heap) memory
//gets freed?
}
return result;
//Same thing here, will the destructor be called for the vector object,
//leading to a memory leak
}
int main(){
std::string input = "hello 123 afsdha 554 asda 12 721";
auto result = return_matches(input);
//printing the result
for(int i = 0; i < result.size(); i++){
std::cout << result[i] << std::endl;
}
}
When should I delete the std::string returned from std::smatch inside a regex iterator, if at all?
You only delete pointers. More specifically, you delete pointers that were returned by a (non-placement) new
expression.
match.str()
doesn't return a pointer. It returns an instance of std::string
. You don't need to, and you cannot delete a std::string
object.
How do you handle a string return value from a library call?
It's a temporary object. Regardless of the way you deal with it, the temporary object is destroyed automatically. There's no risk of memory leak.
Do you copy them to your own string ...
Sure, you can do that if you want to store the string for later.
... that's created by new?
No. That way lies memory leaks. There's hardly ever a need to use new
and even rarer to need to use new
to create a std::string
instance.
Or do you treat them like values and never worry about memory allocation?
Yes. Treat values as values.
//does that mean its destructor is called
Yes. The temporary object is destroyed at the end of the full-expression that contains it.
//and its internal (heap) memory gets freed?
If any memory was allocated by std::string
, it takes care of freeing it.
//Same thing here, will the destructor be called for the vector object,
Yes, objects with automatic storage duration are destroyed automatically at the end of the scope where they are declared.
//leading to a memory leak
No; quite the opposite. Since the destructor frees the memory, there is no leak.