在转换中返回在 lambda 中构造的对象

Returning objects constructed in lambda in transform

以下函数做了一些与我想要的不同的事情,即 return 匹配。如果我在 vector<string>{"a b", "cd ef"} 上调用它,输出是

cd 
cd ef

而不是

a b
cd ef

为什么?

#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
}

没有new也一样:smatch m{};。我认为我不应该这样做,因为 smatch 被分配到堆栈上并在 lambda 函数 return 时失效。 (我什至试过 smatch m;,但这应该创建一个未初始化的变量。奇怪的是,它没有运行时错误,给出了同样的错误结果。)下面甚至没有编译,给出了一个我没有的错误了解:

#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;
}

对于std::match_results

Because std::match_results holds std::sub_matches, each of which is a pair of iterators into the original character sequence that was matched, it's undefined behavior to examine std::match_results if the original character sequence was destroyed or iterators to it were invalidated for other reasons.

lambda的参数s是按值传递的,离开lambda时会被销毁。您可以将其更改为按引用传递:

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
}