Lambda捕获shared_ptr成员

8
我有一个类OpenGLRenderer,其中有一个类成员mMemoryAllocator,它是一个std::shared_ptr<MemoryAllocator>。我将内存分配器保留在shared_ptr中的原因是,即使下面返回的shared_ptr<Texture>比它的创建者OpenGLRenderer还要长寿,如果我通过值捕获它,MemoryAllocator实例仍将有效,因为它会增加引用计数。
std::shared_ptr<Texture> OpenGLRenderer::CreateTexture(TextureType textureType, const std::vector<uint8_t>& textureData, uint32_t textureWidth, uint32_t textureHeight, TextureFormat textureFormat)
{
    return std::shared_ptr<Texture>(mMemoryAllocator->AllocateObject<Texture>(
                                    textureData, textureWidth, textureHeight,
                                    textureFormat, textureType, mLogger), 
                                    [=](Texture* texture) { 
                                        mMemoryAllocator
                                         ->DeallocateObject<Texture>(texture); 
                                    });
}

但是,它不起作用。如果OpenGLRendererstd::shared_ptr<Texture>之前超出范围,那么std::shared_ptr<MemoryAllocator>就会变得损坏,从而导致lambda表达式失控。我做错了什么?


2
当提出问题时,请尽可能地让其他人更容易阅读您的代码。 - David Rodríguez - dribeas
1个回答

11

在这种情况下的问题是Lambda表达式不会捕获对象的成员,而是会捕获this指针。一种简单的解决方法是创建一个本地变量并将其绑定:

std::shared_ptr<Texture> 
OpenGLRenderer::CreateTexture(TextureType textureType, 
                              const std::vector<uint8_t>& textureData, 
                              uint32_t textureWidth, uint32_t textureHeight, 
                              TextureFormat textureFormat)

{
    std::shared_ptr<AllocatorType> allocator = mMemoryAllocator;
    return std::shared_ptr<Texture>(mMemoryAllocator->AllocateObject<Texture>(
                                    textureData, textureWidth, textureHeight,
                                    textureFormat, textureType, mLogger), 
                                    [=](Texture* texture) { 
                                        allocator
                                         ->DeallocateObject<Texture>(texture); 
                                    });
}

1
为什么“=”不能帮助捕获? - KaiserJohaan
4
简而言之,你问题中的 lambda 表达式被处理成 this->mMemoryAllocator->DeallocateObject<Texture>(texture);,所使用的本地 objectthis,而 [=] 将会捕获这个对象。它不会捕获你使用的对象成员,而是 this 指针。你正在按值进行捕获,只是捕获的不是正确的东西。 - David Rodríguez - dribeas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接