The following function does something different than I want, which is to return the matches. If I call it on vector<string>{"a b", "cd ef"}
, the output is
cd
cd ef
instead of
a b
cd ef
Why?
#include <regex>
using namespace std;
void f(const vector<string>& v) {
vector<smatch> P{};
transform(begin(v), end(), back_inserter(P), [](auto s){
auto m = *new smatch;
regex_match(s, m, regex{"(\\S*) (\\S*) ?(.*)"});
return m;
});
for (auto s: P) cout << s[0] << endl; // debug output
}
It's the same if I try without new
: smatch m{};
. Which I believe I shouldn't do, because then the smatch
is allocated on the stack and invalidated when the lambda function returns. (I even tried smatch m;
, but that should create an uninitialized variable. Oddly, it works with no runtime error, giving the same wrong result.) And the following doesn't even compile, giving an error I don't understand:
#include <regex>
using namespace std;
void f(const vector<string>& v) {
vector<smatch> P{};
transform(begin(v), end(), back_inserter(P), [](auto s){
auto m = new smatch;
regex_match(s, m, regex{"(\\S*) (\\S*) ?(.*)"});
cout << (*m)[0] << endl;
return m;
});
for (auto s: P) cout << (*s)[0] << endl;
}
CodePudding user response:
For std::match_results
:
Because
std::match_results
holdsstd::sub_matches
, each of which is a pair of iterators into the original character sequence that was matched, it's undefined behavior to examinestd::match_results
if the original character sequence was destroyed or iterators to it were invalidated for other reasons.
The parameter s
of the lambda is passed by-value, it'll be destroyed when get out of the lambda. You can change it to pass-by-reference:
void f(const vector<string>& v) {
vector<smatch> P;
transform(begin(v), end(v), back_inserter(P), [](auto& s){
// ^
smatch m;
regex_match(s, m, regex{"(\\S*) (\\S*) ?(.*)"});
return m;
});
for (auto s: P) cout << s[0] << endl; // debug output
}