我的项目中的代码如下所示:
class ClassA {
ClassA(int i) : a(i) {};
private:
int a;
};
struct ClassB{
std::shared_ptr<ClassA> classASharedPointer;
};
struct ClassC {
ClassA* classAPointer;
};
void someFunction(std::vector<ClassB> &vecBs, std::vector<ClassC> &vecCs) {
const auto toClassC = [](const auto &b) -> ClassC {
return {b.classASharedPointer.get()};
};
std::transform(vecBs.begin(), vecBs.end(), vecCs.begin(), toClassC);
}
int main() {
std::vector<ClassB> vecBs(5);
std::vector<ClassC> vecCs(5);
someFunction(vecBs, vecCs);
return 0;
}
当我检查 lambda“toClassC”之前和之后的 VM 大小时,我发现有所增加。我没有看到那段记忆被收回。更糟糕的是,我确实有一种感觉,这个 lambda 是错误的,因为我确实有一种感觉,无论它调用了多少其他对象,它都会采用它看到的第一个对象并对其进行操作。
我该如何解决这个问题?
注意:显然,这不是我正在编写的真正代码(哈!令人震惊)。但我尽力提供一个最小的可重复示例。在上面的这段代码中,我没有看到我在原始项目中看到的虚拟内存大小的增加。
为什么我认为它正在泄漏内存(我可能是错的),因为它每次调用函数时都会为该 lambda 分配空间。记忆永远不会被回收。 AFAIK,这不应该发生。并且 lambda 的空间只能保留一次。但我看到的是,例如,如果
main()
调用 someFunction()
两次,我将看到该 lambda 的两次内存分配。
唯一动态分配的内存是为
std::vector
元素分配的,当 vector
在 main()
末尾超出范围时,该内存将自动回收。 someFunction()
和 toClassC
都没有分配任何可能泄漏的动态内存。
当我检查 lambda“toClassC”之前和之后的 VM 大小时,我发现有所增加。而且我没有看到记忆被回收。
toClassC
没有动态分配内存。
更糟糕的是,我确实有一种感觉,这个 lambda 是错误的,因为我确实有一种感觉,无论调用了多少其他对象,它都会采用它看到的第一个对象并对其进行操作。
这是不正确的。
std::transform()
将为 vecBs
中的每个元素调用 lambda。 当第一次调用 lambda 时,其 b
参数将引用第一个 ClassB
对象,然后第二次调用将引用第二个 ClassB
对象,依此类推。 std::transform()
基本上只是在指定范围内的美化循环。
我该如何解决这个问题?
没有什么需要修复的,因为这里没有任何东西损坏。
为什么我认为它正在泄漏内存(我可能是错的),因为它每次调用函数时都会为该 lambda 分配空间。
您使用的是非捕获 lambda,因此它没有内部数据成员可供分配内存。 它基本上是一个空物体。 但它仍然是一个对象(即,它可以传递)。而且由于它不是动态分配的,因此它不会泄漏。
你的代码大致相当于这个:
struct lambda {
ClassC operator()(const ClassB &b) {
ClassC c{b.classASharedPointer.get()};
return c;
};
};
void someFunction(std::vector<ClassB> &vecBs, std::vector<ClassC> &vecCs) {
const lambda toClassC;
auto first1 = vecBs.begin(), last1 = vecBs.end();
auto d_first = vecCs.begin();
for (; first1 != last1; ++d_first, ++first1) {
*d_first = toClassC.operator()(*first1);
}
}
简而言之,对于
ClassB
中的每个 vecBs
元素,您将其 ClassA*
指针分配给 ClassC
中相应的 vecCs
元素。仅此而已。
内存永远不会被回收。 AFAIK,这不应该发生。
没有动态分配的内存需要回收。
并且 lambda 的空间只能保留一次。
这是不正确的。
但是我看到的是,例如,如果 main() 调用 someFunction() 两次,我将看到该 lambda 的两次内存分配。
每次调用
someFunction()
时,它都会在调用堆栈上获取一个新帧来保存其局部变量。当 someFunction()
退出时,该帧将被回收。 toClassC
是 someFunction()
的局部变量,与任何其他局部变量没有什么不同。