【发布时间】:2021-06-23 08:24:22
【问题描述】:
几年前我创建了一个小程序,最近我开始关注使用智能指针。因此,出于实践原因,我根据 Scott Meyers - Effective Modern C++ book 重构了部分代码。
想象一个类,它拥有另一个类的成员 shared_ptr,它管理一些其他不必要对象的生命周期。
class Foo {
...
std::shared_ptr<Bar> manager;
void DoSomeWork();
}
DoSomeWork 方法的实现包含一个 lambda collectIfNeighbor,因为它在某些部分经常使用,这是实现正确行为的最简单方法。主要思想是只捕获 lambda 中需要的内容,并使用智能指针而不是到处检查 nullptr。
void Foo::DoSomeWork(){
std::vector<Object*> neighbors;
auto collectIfNeighbor = [this, &neighbors](const Position& pos) {
...
if ( *some condition* )
neighbors.push_back(manager->GetObject(pos));
};
collectIfNeighbor(Position(1,1)); // example usage
...
}
所以这里的问题是我在 lambda 内部捕获了this,但我并不需要全部,只需要经理。将 shared_ptr 传递给 lambda 的最有效方法是什么?
如果可能,我不想传递整个this,因为我只使用一个成员。要么我不想创建和销毁大量的 shared_ptrs,因为它会使它变慢。另外,不用关心经理是否还活着也不错。
还有其他实现 lambda 的方法。将 shared_ptr 复制到本地,并通过引用传递它。但是我在本地制作和额外的副本,我担心每次 lambda 调用时。另一种方法是简单地创建一个常规指针并将其传递给 lambda。
std::shared_ptr<Bar> localManager = manager;
auto lambdaV1= [&localManager, &neighbors](const Position& pos) {
...
if ( *some condition* )
neighbors.push_back(manager->GetObject(pos));
};
Bar* localManagerPtr = manager.get();
auto lambdaV2= [&localManagerPtr , &neighbors](const Position& pos) {
...
if ( *some condition* && manager != nullptr) // extra check on manager
neighbors.push_back(manager->GetObject(pos));
};
我检查了Passing shared_ptr to lambda cause memory leak 和Capture by universal ref,但对我没有多大帮助。
【问题讨论】:
-
不参与所有权时,传递原始指针
-
"我不想传递整个 this" 听起来您担心捕获
this会复制对象。但是捕获this只捕获一个指针。 -
除非您打算更改
localManagerPtr指向的对象,否则您应该只按值捕获指针。 -
捕获
this可能是最简单和最便宜的解决方案。除非您担心this的生命周期会超过 lambda,否则您应该坚持下去。 -
C++14 允许“(重新)命名”捕获,如果你想更明确的话。
标签: c++ c++11 lambda shared-ptr