You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中不派生Clone trait如何强制传值?Window结构体返回报错求助

问题

我是Rust新手,尝试返回如下Window结构体:

pub struct Window<'a> {
    ev_loop: EventLoop<()>,
    window_builder: WindowBuilder,
    context_builder: ContextBuilder<'a, NotCurrent>,
    display: Display
}

并通过以下函数返回该结构体:

pub fn init_lib () -> Window<'static> {
    let event_loop = glutin::event_loop::EventLoop::new();
    let wb = glutin::window::WindowBuilder::new();
    let cb = glutin::ContextBuilder::new();
    let display = glium::Display::new(wb, cb, &event_loop).unwrap();

    return Window {
        ev_loop: event_loop,
        window_builder: wb,
        context_builder: cb,
        display: display
    }
}

但返回wb作为window_builder、cb作为context_builder时出现错误:

use of moved value: `cb`
value used here after moverustcE0382
lib.rs(32, 43): value moved here
lib.rs(31, 9): move occurs because `cb` has type `ContextBuilder<'_, NotCurrent>`, which does not implement the `Copy` trait

我使用的是glium库,无法修改源码,请问如何解决?另外,如何在Rust中不派生Clone trait的情况下强制传值?

解决方案

针对当前glium场景的解决办法

问题核心是glium::Display::new会转移(move)传入的WindowBuilder和ContextBuilder的所有权,所以这两个变量在调用完new之后就不能再被使用了。你有两种可行的处理方式:

  1. 放弃存储原始的构建器实例
    如果你的Window结构体不需要保留window_builder和context_builder,直接移除这两个字段即可:
pub struct Window<'a> {
    ev_loop: EventLoop<()>,
    display: Display
}

pub fn init_lib () -> Window<'static> {
    let event_loop = glutin::event_loop::EventLoop::new();
    let wb = glutin::window::WindowBuilder::new();
    let cb = glutin::ContextBuilder::new();
    let display = glium::Display::new(wb, cb, &event_loop).unwrap();

    Window {
        ev_loop: event_loop,
        display: display
    }
}
  1. 克隆构建器再传入Display::new
    WindowBuilder和ContextBuilder本身已经实现了Clone trait(glium/glutin的公开API设计如此),可以先克隆一份用于创建Display,保留原始实例存入结构体:
pub fn init_lib () -> Window<'static> {
    let event_loop = glutin::event_loop::EventLoop::new();
    let wb = glutin::window::WindowBuilder::new();
    let cb = glutin::ContextBuilder::new();
    // 克隆构建器用于创建Display,原始实例保留
    let display = glium::Display::new(wb.clone(), cb.clone(), &event_loop).unwrap();

    Window {
        ev_loop: event_loop,
        window_builder: wb,
        context_builder: cb,
        display: display
    }
}

关于“不派生Clone强制传值”的说明

在Rust中,不存在“不实现Clone就强制传值”的语法——所有权规则是语言的核心约束,目的是避免内存安全问题。如果一个类型没有实现Copy或Clone,你只能通过以下方式转移或复用它:

  • 转移所有权(move):变量只能被move一次,之后原变量不可再用;
  • 借用(borrow):通过引用&T或可变引用&mut T临时访问变量,但所有权仍属于原持有者;
  • 使用智能指针:比如Rc<T>或Arc<T>,允许多个所有者共享同一实例,但会带来运行时开销,且需要类型满足Sync/Send(根据场景)。

回到你的场景,WindowBuilder和ContextBuilder已经实现了Clone,直接用克隆是最简洁且符合API设计的方案。

内容的提问来源于stack exchange,提问作者NaniNoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:35:19