生命周期和对包含引用的对象的引用

2023-11-22

假设我有一个包含引用的结构,以及另一个包含对该结构的引用的结构,如下所示:

struct Image<'a> {
    pixel_data: &'a mut Vec<u8>,
    size: (i32, i32),
}

struct SubImage<'a> {
    image: &'a mut Image<'a>,
    offset: (i32, i32),
    size: (i32, i32),
}

这些结构体具有几乎相同的接口,区别在于SubImage在转发到所包含的相应函数之前,根据其偏移量调整位置参数Image参考。我希望这些结构大部分可以互换,但我似乎不知道如何获得正确的生命周期。最初,我只是使用Image,并且可以简单地传递对象,而无需考虑生命周期说明符:

fn main() {
    let mut pixel_data: Vec<u8> = Vec::new();
    let mut image = Image::new(&mut pixel_data, (1280, 720));
    render(&mut image);
}

fn render(image: &mut Image) {
    image.rect_fill(0, 0, 10, 10);
}

然后我创建了SubImage,并想做这样的事情:

fn render2(image: &mut Image) {
    let mut sub = SubImage {
        image: image,           // line 62
        offset: (100, 100),
        size: (600, 400),
    };

    sub.rect_fill(0, 0, 10, 10);
}

然而,这会导致编译器错误:

main.rs:62:16: 62:21 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements

编译器的建议是将签名更改为:

fn render2<'a>(image: &'a mut Image<'a>)

然而,这只是将问题推向了调用的函数render2,并采取了&mut Image。这很烦人,因为函数调用要深入几层,而当我只是使用Image类(也有一个引用),并内联调整偏移量。

所以首先,我什至不明白为什么这是必要的(诚然,我对 Rust 寿命的理解是有限的)。其次(我的主要问题),我能做些什么 SubImage 使这些明确的生命周期变得不必要?


是的,这个错误可能令人困惑,但它是有正当理由的。

struct SubImage<'a> {
    image: &'a mut Image<'a>,
    offset: (i32, i32),
    size: (i32, i32),
}

在这里你声明引用Image必须活下去完全一样长作为图像本身内部借用的数据 - 相同的生命周期参数'a既用于参考又用作参数Image: &'a mut Image<'a>.

然而,render2()违反此要求。实际签名为render2()如下:

fn render2<'b, 'a>(image: &'b mut Image<'a>)

因此,它试图创造SubImage with &'b mut Image<'a>, where 'b不一定等于'a(在这种特殊情况下,它肯定不会),因此编译器会退出。

此外,这样的签名是您可以在提供该函数时调用该函数的唯一原因&mut image in main(), 因为&mut image有生命周期image变量,但是Image该变量包含的生命周期为pixel_data稍长一些。以下代码不是有效的 Rust,但它接近编译器理解事物的方式,并且它演示了问题:

fn main() {
    'a: {
        let mut pixel_data: Vec<u8> = Vec::new();
        'b: {
            let mut image: Image<'a> = Image::new(&'a mut pixel_data, (1280, 720));
            render2::<'b, 'a>(&'b mut image);
        }
    }
}

当你声明render2() as

fn render2<'a>(image: &'a mut Image<'a>)

你确实将问题“推”到了上游 - 现在该函数根本无法被调用&mut image,你现在可以明白为什么了——它需要统一'a and 'b一生,这是不可能的,因为'a长于'b.

正确的解决方案是使用单独的生命周期来参考Image and Image本身在SubImage定义:

struct SubImage<'b, 'a:'b> {
    image: &'b mut Image<'a>,
    offset: (i32, i32),
    size: (i32, i32),
}

Now 'b and 'a可能有不同的生命周期,但为了使其发挥作用,你必须绑定'a一生与'b, 那是,'a必须至少活到'b。这正是您的代码所需的语义。如果不强制执行此约束,则引用的图像可能会在引用超出范围之前“死亡”,这违反了 Rust 的安全规则。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

生命周期和对包含引用的对象的引用 的相关文章

随机推荐

  • 如何知道DIV中的所有元素是否已完全加载?

    有一个div其中将通过 Ajax 加载一些元素 图像 iframe 等 这些元素完全加载后 我需要执行一个函数div 如何确定数组中的所有元素div已满载 我使用 jQuery 作为库 对于图像和 iframe 您可以使用load even
  • 将MySQL的POINT转换为PHP中的文本

    使用 PHP 如何将值转换为POINT数据类型为字符串 例如POINT 34 601020 58 371020 最好以 WKT 或 GeoJSON 形式输出 如果我回显原始值 我会得到奇怪的字符 我尝试过使用bin2hex然后尝试将十六进制
  • for循环中的lambda仅取最后一个值[重复]

    这个问题在这里已经有答案了 我有代码 options INFO WARNING DEBUG for i in range len options option options i cMenu add command label format
  • Perl 查找函数

    这个问题就解决了 非常感谢 我的问题和我正在使用的解决方案如下所述 问题 open IN lt test txt seek IN 10 0 read IN temp 5 seek IN 20 0 close IN 情况是 我的句柄将从位置
  • PostgreSQL 查询时间过长

    我的数据库有几亿行 我正在运行以下查询 select from Payments as p inner join PaymentOrders as po on po Id p PaymentOrderId inner join Users
  • 在 C++ 中的输出字符串中插入“£”符号

    我有以下代码 cout lt lt String that includes a sign 但是 编译器无法识别 符号 而是显示带重音符号的 u 我可以使用以下方法插入一个 cout lt lt String that includes a
  • 如何在数据表中引用数据表父级?

    考虑一个虚拟案例
  • 如何更改 Angular2 TypeScript 项目中的 body 类

    我的登录页面和应用程序中的其他页面有不同的类 因此用户登录后我需要更改 body 元素的类 这是我如何努力实现这一目标的 索引 html
  • 为实体框架创建动态表达式

    我创建了一个通用表达式生成器 它根据条件集合构建谓词 我将谓词传递给存储库中的通用方法 我认为表达式生成器工作正常并创建所需的谓词 尽管实体框架生成的 SQL 脚本不符合我的预期 我读过很多关于动态查询或 LinqKit 和表达式生成器的问
  • 如何检测我的用户正在使用哪个 iOS 设备?

    我正在寻找一种方法来检测我的应用程序正在运行的设备 我对软件版本不感兴趣 我搜索了很多问题 但没有一个 令人惊讶地 满足我的需求 原因如下 解决方案一 NSString deviceType UIDevice currentDevice m
  • 用于网络表单的打字稿

    Web 表单支持 Typescript 吗 我有一个现有的 asp net 4 5 Web 表单项目 其中打字稿似乎不起作用 我无法创建新文件 但即使我将现有文件重命名为 ts 它似乎也不起作用 没有构建 没有智能感知 什么都没有 找到了我
  • Pygame 导致 FPS 低的原因。如何提高性能?

    我正在使用 pygame 处理一些射弹 发现即使只有 200 行代码 游戏的运行速度也低于 50 fps 除了运行循环之外 没有大循环 而且我的电脑相当新 那么 这是因为 pygame 使用 SDL 吗 如果是这样 使用像 OpenGL 这
  • 如何设置savon默认超时值

    我正在使用 savon 进行一些 api 调用 但它需要很长时间才能响应 因为我收到超时错误 所以有什么方法可以更改超时的默认值 我正在使用 savon 0 7 9 ruby 1 8 7 和rails v 2 3 2 Savon 使用 ge
  • 基类和继承中的静态方法中的静态变量

    我有这些 C 类 class Base protected static int method static int x 0 return x class A public Base class B public Base 会不会x静态变量
  • 当数据源为 Linq 时访问 ItemDataBound 事件中的列

    我使用以下代码设置数据源 protected void Page Load object sender EventArgs e var vacancies from v in db Vacancies join c in db Custom
  • 避免传递数据框的最佳方法是什么?

    我有12个data frame一起工作 它们是相似的 我必须对每一个进行相同的处理 所以我编写了一个函数 它需要一个data frame 处理它 然后返回一个data frame 这有效 但我担心我正在绕过一个非常大的结构 我可能正在制作临
  • 如何使用正则表达式分割字符串

    我想将一个字符串拆分为列表或数组 Input green yellow green white orange blue black 分割字符是逗号 但它必须忽略引号内的逗号 输出应该是 green 黄绿色 white orange 蓝黑 T
  • mvc.net验证是否支持ValidationGroup的概念

    来自 asp net 的背景 在向页面添加验证时 我非常欣赏 validationGroup 的概念 我一直在 mvc net 中寻找相应的概念 但运气不佳 这个概念在 mvc net 中可用吗 如果没有 我还有什么选择 不幸的是 它没有附
  • 有人有渲染 HTML 的 diff 算法吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我有兴趣看到一个好的 diff 算法 可能是用 Javascript 编写的 用于渲染两个 HTML 页面的并排差异 这个想法是 diff 将显示差
  • 生命周期和对包含引用的对象的引用

    假设我有一个包含引用的结构 以及另一个包含对该结构的引用的结构 如下所示 struct Image lt a gt pixel data a mut Vec