mutable 允许修改lambda成员变量

mutable

在 C++ 中,mutable 关键字可以用在不同的上下文中。在你提供的代码中,mutable 出现在 lambda 表达式中,它有以下两个主要用途:

  1. 允许修改捕获的变量: 当你在 lambda 表达式中捕获变量时(默认是按值捕获),这些捕获的变量在 lambda 内是不可修改的。使用 mutable 关键字可以让你在 lambda 内部修改这些捕获的变量。
  2. 允许修改成员变量: 如果 lambda 表达式是一个类的成员函数的一部分,并且该成员函数本身是 const,那么 mutable 也可以让你在 lambda 内部修改类的成员变量。

在你的代码中,mutable 的作用主要是第一个用途,即允许在 lambda 表达式内部修改捕获的变量。具体来说,以下是代码中的部分:

Async(EAsyncExecution::TaskGraph, [=, func = std::move(func)]() mutable
{
    // 构建缩略图文件路径
    FString path = FString::Printf(TEXT("%s/%s"), *FGamePath::GetThumbnailDir(), *id);
    TArray64<uint8> imgData; // 用于存储从文件中读取的图像数据
    
    // 检查文件是否存在并将其内容加载到imgData数组中
    if (!IsFileExists(path) || !FFileHelper::LoadFileToArray(imgData, *path))
    {
        func(nullptr); // 如果文件不存在或加载失败,调用回调函数并传递null指针
        return;
    }
    
    // 在主线程上执行异步任务以创建纹理
    AsyncTask(ENamedThreads::GameThread, [=, func = std::move(func)]() mutable
    {
        UTexture2D* texture = GetTextureFromByteArray(imgData); // 从字节数组创建纹理
        if (texture != nullptr)
        {
            // 将纹理添加到LRU缓存中
            TextureLRU->Add(id, texture);
            // 可以选择性更新资源(已注释掉)
            // texture->UpdateResource();
        }
        else {
            // 如果纹理创建失败,删除文件
            IFileManager::Get().Delete(*path);
        }
        // 调用回调函数并传递创建的纹理
        func(texture);
    });
});

在这个例子中,有两个地方使用了 mutable

Async(EAsyncExecution::TaskGraph, [=, func = std::move(func)]() mutable
{
    // ...
});

AsyncTask(ENamedThreads::GameThread, [=, func = std::move(func)]() mutable
{
    // ...
});

为什么这里需要 mutable

  • 捕获的变量按值传递:在这段代码中,lambda 捕获变量是按值捕获的(使用 [=]),这意味着它们在 lambda 内部被视为 const。如果我们需要在 lambda 内部修改这些捕获的变量,例如 func,我们就需要使用 mutable 关键字来解除这种限制。
  • 转移所有权:特别是对于 func = std::move(func),我们需要修改 func 以转移其所有权(使用 std::move)。如果没有 mutable,在按值捕获的情况下,func 会被视为 const,我们无法对其进行 std::move 操作。

通过在 lambda 表达式中使用 mutable,我们可以在 lambda 内部修改这些捕获的变量,从而实现所需的功能。

posted @ 2024-06-21 11:51  Dream_moon  阅读(95)  评论(0)    收藏  举报