- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
恐怕这可能是非常基础的,但我自己还没有弄明白。我有这张 map :
subscriptions_map: HashMap<SubscriptionKey, Subscription<'a>>
和这个向量:
subscriptions: Vec<&'a Subscription<'a>>,
我想在 HashMap
中插入一个值以及对同一项目的引用到向量中。我试过这样做:
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
self.subscriptions.push(subs);
但它得到这个错误:
error: borrowed value does not live long enough
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: reference must be valid for the lifetime 'a as defined on the block at 40:70...
pub fn add_subscription(&'a mut self, mut item: Subscription<'a>) {
let id = item.get_id();
let _lock = self.lock.lock().unwrap();
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
...
note: ...but borrowed value is only valid for the block suffix following statement 2 at 45:87
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
self.subscriptions.push(subs);
}
error: aborting due to previous error
我想我的问题可以归结为:如果我有一个 Option<T<'a>>
, 我怎样才能得到 &'a T
?
最佳答案
HashMap.insert()
返回给定键的 old 值,而不是您刚刚传递的值。这不是你想要的!
将项目插入 HashMap
后,您必须调用 HashMap.get()
检索指向该值的指针。作为HashMap.insert()
拥有键和值的所有权,我们需要传递 id
的克隆至 insert()
所以我们可以使用原来的 id
对于 get()
称呼。 (如果 id
的类型是 Copy
,您可以省略对 clone()
的调用并让编译器复制该值。)
use std::collections::HashMap;
#[derive(Eq, PartialEq, Hash, Clone)]
struct SubscriptionKey;
struct Subscription<'a>(&'a ());
struct Foo<'a> {
subscriptions_map: HashMap<SubscriptionKey, Subscription<'a>>,
subscriptions: Vec<&'a Subscription<'a>>,
}
impl<'a> Foo<'a> {
fn add(&'a mut self, id: SubscriptionKey, item: Subscription<'a>) {
self.subscriptions_map.insert(id.clone(), item);
let subs = self.subscriptions_map.get(&id).unwrap();
self.subscriptions.push(subs);
}
}
fn main() {
let subscription_data = &();
let mut f = Foo {
subscriptions_map: HashMap::new(),
subscriptions: Vec::new(),
};
f.add(SubscriptionKey, Subscription(subscription_data));
}
这工作正常,但如果我们尝试添加另一个订阅,它就会崩溃。如果我们这样做:
fn main() {
let subscription_data = &();
let subscription_data2 = &();
let mut f = Foo {
subscriptions_map: HashMap::new(),
subscriptions: Vec::new(),
};
f.add(SubscriptionKey, Subscription(subscription_data));
f.add(SubscriptionKey, Subscription(subscription_data2));
}
编译器给出以下信息:
<anon>:30:5: 30:6 error: cannot borrow `f` as mutable more than once at a time [E0499]
<anon>:30 f.add(SubscriptionKey, Subscription(subscription_data2));
^
<anon>:30:5: 30:6 help: see the detailed explanation for E0499
<anon>:29:5: 29:6 note: previous borrow of `f` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `f` until the borrow ends
<anon>:29 f.add(SubscriptionKey, Subscription(subscription_data));
^
<anon>:31:2: 31:2 note: previous borrow ends here
<anon>:20 fn main() {
...
<anon>:31 }
^
这是怎么回事?为什么可变借用在第一次调用 Foo::add
后仍然存在?
问题来自 subscriptions
的定义 field 。它被定义为 Vec<&'a Subscription<'a>>
.满足 'a
在Subscription<'a>
很简单,因为我们在 add
中收到了具有正确生命周期的对象.满足 'a
在&'a ...
更难,因为 Subscription<'a>
在我们将其插入 subscriptions_map
之前,该值没有固定地址(在我的示例中,Subscription<'a>
从 main()
中的局部变量移动到 Foo::add()
中的参数到 self.subscriptions_map
内部)。
为了满足外'a
, Foo::add()
必须定义它的 self
参数为 &'a mut self
.如果我们将其定义为 &mut self
, 我们不能确定我们从 subscriptions_map
中得到的引用会活得足够长(它们的生命周期可能比 'a
短)。
但是,通过插入 &'a Subscription<'a>
在 Foo<'a>
里面,我们有效地锁定 Foo
为了进一步修改,因为我们现在正在存储来自 self.subscriptions_map
的借用在self.subscriptions
.考虑一下如果我们在 subscriptions_map
中插入另一个项目会发生什么: 我们如何确定 HashMap
不会在内存中移动它的项目?如果HashMap
确实移动了我们的项目,self.subscriptions
中的指针不会自动更新并且会悬空。
现在,假设我们有这辆马车 remove()
方法:
impl<'a> Foo<'a> {
fn remove(&mut self, id: &SubscriptionKey) {
self.subscriptions_map.remove(id);
}
}
此方法编译正常。但是,如果我们试图在 Foo
上调用它我们称之为add()
早点,然后 self.subscriptions
将包含对曾经在 self.subscriptions_map
中的项目的悬空引用.
所以可变借用在调用add()
后仍然存在的原因就是这样,因为'a
在Foo<'a>
等于 Foo<'a>
的生命周期自身,编译器认为对象是从自身借用的。如您所知,我们不能同时激活一个可变借用和另一个事件借用(可变或不可变),因此 Rust 阻止我们在 f
上进行可变借用。同时f
本身保留主动借用。事实上,因为我们使用了一个方法,需要 self
通过可变引用,Rust 假定 Foo<'a>
存储一个可变引用,即使事实并非如此,因为 Rust 只查看签名来确定借用(这是为了确保将私有(private)字段从 &'a T
更改为 &'a mut T
不会导致您和借用检查失败,如果你正在开发一个图书馆,给你的用户)。由于对象的类型永远不会改变,Foo<'a>
在其剩余生命周期内被锁定。
现在,你能做什么?显然,您不能有用地拥有 Vec<&'a Subscription<'a>>
在你的结构中。 HashMap
提供一个 values()
迭代器,但它以未指定的顺序枚举值,因此如果您想按照添加它们的顺序枚举值,它不会帮助您。您可以使用 Rc
而不是使用借来的指针:
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Eq, PartialEq, Hash)]
struct SubscriptionKey;
struct Subscription<'a>(&'a ());
struct Foo<'a> {
subscriptions_map: HashMap<SubscriptionKey, Rc<Subscription<'a>>>,
subscriptions: Vec<Rc<Subscription<'a>>>,
}
impl<'a> Foo<'a> {
fn add(&mut self, id: SubscriptionKey, item: Subscription<'a>) {
let item = Rc::new(item);
self.subscriptions_map.insert(id, item.clone());
self.subscriptions.push(item);
}
}
fn main() {
let subscription_data = &();
let mut f = Foo {
subscriptions_map: HashMap::new(),
subscriptions: Vec::new(),
};
f.add(SubscriptionKey, Subscription(subscription_data));
}
关于reference - 获取&'a T from Option<T<' a>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36138477/
我想在 java 中声明一个对象,就像在 C++ 中指向指针的指针,让我给你看一个例子: //*** At the application startup //Initialize a setting
考虑这段代码, struct A {}; struct B { B(const A&) {} }; void f(B) { cout << "f()"<
我正在尝试将一个C程序翻译成Rust。。C程序具有以下结构(归结为MRE):。在一个函数中,我将执行以下指针魔术:。不,我的问题是:我将如何在铁锈中实现同样的目标?。到目前为止,我在《铁锈》中尝试过的
我目前正在尝试将一个C程序翻译成Rust。。C程序具有以下结构(归结为MRE):。在一个函数中,我将执行以下指针魔术:。不,我的问题是:我将如何在铁锈中实现同样的目标?。到目前为止,我在《铁锈》中尝试
这个问题在这里已经有了答案: Add managed DLL dependencied to unmanaged C++ project (1 个回答) 关闭 6 年前。 我有这样一个场景: 使用
这是一个常见问答的集合,这也是一个社区维基,所以每个人都被邀请参与维护它。。正则表达式正在遭受给我ZE代码类型的问题和没有解释的糟糕答案。此参考旨在提供指向质量问答的链接。。此参考适用于以下语言:PH
我正在尝试在方案中模拟堆栈。我正在使用 DrScheme 并选择语言 R5RS。我需要创建 pop、push 和 peek 的函数。但我无法弄清楚如何通过引用传递。我已经阅读了一些关于盒子的信息,但是
我陷入了这个错误。我将代码部署在生产服务器上,它在端口 80 上运行。当我尝试登录管理页面时。如图所示,它给了我 403 错误。 可能是什么原因?我的 Django 代码或 nginx 配置有问题吗?
这是一段简单的 C++ 代码: A foo(){ A a; // create a local A object return a; } void bar(const A & a_r){ }
我正在使用从 torrenteditor 获取的 php 脚本来创建 torrent 文件,但是当我使用指定的方法创建新的 torrent 文件时,torrent 文件被创建但我收到很多通知。,就像这
MySQL: REFERENCES vs FOREIGN KEY + REFERENCES 我认为 REFERENCES 是更冗长的 FOREIGN KEY REFERENCES 语法的某种速记语法。
我想使用基于另一个方法引用的方法引用。这有点难以解释,所以我给你举个例子: Person.java public class Person{ Person sibling; int a
Java/C# 语言律师喜欢说他们的语言通过值传递引用。这意味着“引用”是在调用函数时复制的对象指针。 同时,在 C++ 中(以及在 Perl 和 PHP 中更动态的形式),引用是某个其他名称(或动态
当我需要实现递归 lambda 时,通常我这样做: auto factorial = [](auto& self, int n) -> int { return n == 0 ? 1 : n
我目前正在研究 DDD ,需要一些启发。 我有两个实体 Temple TempleVariant Temple(听筒)包含基本信息(名称,描述等),并具有n个变体,它们具有技术描述(CAD绘图,尺寸,
在 Grails 中 belongsTo允许一个域类与另一个域类建立级联关系。使用belongsTo时有两种类型的关系:引用和无引用。 Reference 在拥有的对象上创建属性,而 No Refer
我正在使用 AWS 和 Django Rest Framework 开发 Web 应用程序。(Django:v1.8,DRF:v3) 我一直在为 POST 多部分表单请求获取 django.reque
我按照下面的定义公开了 WCF 端点, 当我在 .NET 3.5 中添加“服务引用”时,我们在代理中获得了以下类,这非常好: [Syst
我在玩 constexpr 引用时产生了这种感觉。但问题本身与 constexpr 无关,只是被它揭示。 我们知道有“指向const的指针”,也有“const指针”。顺便说一句,由于后者的使用比前者少
我有 2 种类型的 refences,它们中的每一种都可以正常工作。 我尝试使用每一个并在 project build 中得到相同的结果。 请向我解释 COM 引用和引用之间的区别。 谢谢你。 最佳答
我是一名优秀的程序员,十分优秀!