那是因为make_pipeable
它以价值为依据。这是 src 代码中的定义:
struct make_pipeable_fn
{
template<typename Fun>
detail::pipeable_binder<Fun> operator()(Fun fun) const
{
return {std::move(fun)};
}
};
由于您是std::map<int, int>
通过引用返回的,因此它指向已被移动的对象的地址。(std::move
在上面的调用中)
如果这不是很清楚,请考虑一个更简单的示例。在下面的代码中,Noisy 只是一个发出调用的结构。
#include <iostream>
#include <range/v3/utility/functional.hpp>
using namespace ranges;
struct Noisy
{
Noisy() { local_ = ++cnt_; std::cout << "Noisy() ctor " << local_ << '\n'; }
Noisy(const Noisy&) { local_= ++cnt_; std::cout << "Noisy(Noisy&) copy ctor " << local_ << '\n'; }
Noisy(Noisy&&) { local_ = ++cnt_; std::cout << "Move constructor " << local_ << '\n'; }
~Noisy() { std::cout << "~Noisy() dtor with local " << local_ << '\n'; }
// global object counter
static int cnt_;
// local count idx
int local_ = 0;
};
int Noisy::cnt_ = 0;
auto counter = []()
{
Noisy n;
return make_pipeable([=](auto x) { return n; });
};
int main(int argc, char *argv[])
{
auto steps = counter();
std::cout << "Deleting" << '\n';
return 0;
}
上面代码的输出是这样的:
Noisy() ctor 1
Noisy(Noisy&) copy ctor 2
Move constructor 3
Move constructor 4
~Noisy() dtor with local 3
~Noisy() dtor with local 2
~Noisy() dtor with local 1
Deleting
~Noisy() dtor with local 4
如您所见,对象2
(在您的情况下持有std::map<int, int>
)在行打印之前被销毁Deleting
。steps
是一个pipeable_binder
结构,它从我们传递的 lambda 扩展而来,并在最后被销毁。