Bar*_*klı 13 c++ lambda shared-ptr
我有以下代码:
void MyClass::onOpenModalBtnClicked() {
uiManager->load(L"data/ui/testmodal.json");
std::shared_ptr<UIElement> modal = uiManager->getElementById("loginModal");
if(modal) {
modal->getElementById("closeButton")->onClicked = [modal]() {
modal->hide();
};
}
}
Run Code Online (Sandbox Code Playgroud)
这个工作正常,点击按钮时模态关闭,onClicked是std::function.
我的应用程序开头也有这个:
#if defined(DEBUG) | defined (_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
Run Code Online (Sandbox Code Playgroud)
这会在应用程序终止时打印出内存泄漏.
使用上面的代码我得到了很多内存泄漏,如果我将代码更改为以下代码,它们都会消失:
void MyClass::onOpenModalBtnClicked() {
uiManager->load(L"data/ui/testmodal.json");
std::shared_ptr<UIElement> modal = uiManager->getElementById("loginModal");
if(modal) {
modal->getElementById("closeButton")->onClicked = [this]() {
uiManager->getElementById("loginModal")->hide();
};
}
}
Run Code Online (Sandbox Code Playgroud)
我假设传递in shared_ptr值会使ref计数增加1,然后这个引用永远不会超出范围,或者在报告mem泄漏后它超出范围.所以我在使用shared_ptr之后尝试在lambda中调用reset但是后来我得到了这个编译错误:
Error 1 error C2662: 'void std::shared_ptr<_Ty>::reset(void) throw()' : cannot convert 'this' pointer from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty> &'
所以问题是如何使用捕获modal而不是那些内存泄漏?
编辑:
所以我通过添加mutable到lambda 摆脱了编译错误.
if(modal) {
modal->getElementById("closeButton")->onClicked = [modal]() mutable {
modal->hide();
modal.reset();
};
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我单击关闭按钮,并关闭应用程序,则没有内存泄漏,因为重置会清除该引用.但如果从未点击按钮,我仍然会收到泄漏.
Cor*_*ica 16
您已创建shared_ptr循环.
在其引用计数达到0之前,不能销毁模态.然后将shared_ptr的副本传递给模态到labmda函数,增加其引用计数.然后,将该lambda函数分配给modal的成员.
这意味着modal总是由其回调函数引用.但是,在modal没有refcount之前,它的回调函数不能被销毁.Modal最终会因为引用计数为1而陷入困境.
通常的解决方案是将裸指针或(最好)弱指针传递给lambda
| 归档时间: |
|
| 查看次数: |
9350 次 |
| 最近记录: |