这编译:
[]{};
Run Code Online (Sandbox Code Playgroud)
这也是:
[]() mutable {};
Run Code Online (Sandbox Code Playgroud)
但是使用这段代码,编译器会向我抛出错误消息:
[] mutable {};
^~~~~~~
error: lambda requires '()' before 'mutable'
Run Code Online (Sandbox Code Playgroud)
有什么特别的理由吗?
常见的相等/比较成员设计指南是不在可变引用类型上实现结构相等,而是查看具有可变字段的F#记录类型:
type Value = { mutable value: int }
let mutableRecord = { value = 1 }
let xs = Map.ofList [ mutableRecord, "abc"
{ value = 2 }, "def" ]
let abc = Map.find { value=1 } xs
mutableRecord.value <- 3
let abc = Map.find { value=3 } xs // KeyNotFoundException!
Run Code Online (Sandbox Code Playgroud)
它Map是内部排序的,但是mutable记录字段允许我更改排序,而记录实例已经在map中,这非常糟糕.
我认为F#应该推断[<NoEquality>]和[<NoComparison>]声明可变字段的F#记录类型的模式,不是吗?
我想更改另一个结构中数组中结构的值:
struct Foo<'a> {
bar: &'a [&'a mut Bar]
}
struct Bar {
baz: u16
}
impl<'a> Foo<'a> {
fn add(&mut self, x: u16) {
self.bar[0].add(x);
}
}
impl Bar {
fn add(&mut self, x: u16) {
self.baz += x;
}
}
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误:
struct Foo<'a> {
bar: &'a [&'a mut Bar]
}
struct Bar {
baz: u16
}
impl<'a> Foo<'a> {
fn add(&mut self, x: u16) {
self.bar[0].add(x);
}
}
impl Bar {
fn add(&mut self, x: u16) {
self.baz …Run Code Online (Sandbox Code Playgroud) 我List在一个由鲜为人知的专有框架管理的类中有一个字段。
注释@BindMagic由框架管理,因此底层列表有时会发生变化:它可能会被重新创建或其元素可能会发生变化。
class SharedEntity{
@BindMagic // this annotation does a magic that we cannot control
private List<Map<String,Object>> values;
public boolean isChangedSincePreviousCall(){
// check if "values" have changed since the previous call of this method
}
}
Run Code Online (Sandbox Code Playgroud)
我同意这是一个糟糕的设计,但让我们假设没有可能影响它。
不时(不是在每个突变上)需要检查列表是否已更改。例如,我想用 method 来做isChangedSincePreviousCall。也许,像哈希和这样的东西会很好。但我很好奇有没有更好的方法。
检测列表是否更改的最佳做法是什么?
我想将一个FnMut闭包包装成RefCell如下所示:
fn borrow_mut_closure() {
let mut temp = 3i32;
let cl = RefCell::new(move || {
temp += 1;
println!("{}", temp);
});
cl.borrow_mut()();
}
Run Code Online (Sandbox Code Playgroud)
但令我惊讶的是,编译器报告:
cannot borrow data in a dereference of `std::cell::RefMut<'_, [closure@src/main.rs:17:25: 20:4 temp:i32]>` as mutable
cannot borrow as mutable
help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::cell::RefMut<'_, [closure@src/main.rs:17:25: 20:4 temp:i32]>`rustc(E0596)
Run Code Online (Sandbox Code Playgroud)
但为什么不实施呢?我怎样才能克服这个问题?
我已经阅读了这些文档:https : //doc.rust-lang.org/rust-by-example/scope/borrow/mut.html
我也读过这个问题:(不能将不可变的借用内容作为可变借用)
这些文档帮助我理解了如何将借用声明为可变的(我认为):
let mut (part1, part2) = someTuple;
Run Code Online (Sandbox Code Playgroud)
但是我一直无法找到关于什么是不可变的借用的明确说明。这是我的猜测:
let (part1, part2) = someTuple;
Run Code Online (Sandbox Code Playgroud)
我知道这是一个非常基本的问题,但谷歌搜索让我深入到解释的深处,我仍然试图在最简单的上下文中找到我的方向。
我如何在 Rust 中借用可变和不可变?
我被困在一次更新 300 多个联系人的问题上。当我尝试将真实联系人的 mutablecontact 图像更新为 mutablablecopy 时,发生内存泄漏。
RAM 使用量超过 1.4GB,然后应用程序崩溃。这是我的代码。
if let mutableCopy = contact.mutableCopy() as? CNMutableContact {
ImageDownloader.default.downloadImage(with: URL(string: thumbnailImageURL)!) { result in
switch result {
case .success(let value):
queue.sync {
SVProgressHUD.show(withStatus: "loading 1")
//mutableCopy.imageData = compressedImage?.pngData()
mutableCopy.imageData = value.image.pngData() //self.returnCustomSizeImage(image: value.image).pngData()
mutableCopy.givenName = givenName
mutableCopy.phoneNumbers = [CNLabeledValue(label: self.responsedContactsArray[index2].label ?? "NO DOB", value: CNPhoneNumber(stringValue: "\(trimmedPhoneNumber)"))]
//mutableCopy.familyName = "?"
saveRequest.update(mutableCopy)
do {
try AppDelegate.mContactStore.execute(saveRequest)
} catch let error {
SVProgressHUD.dismiss()
}
}
Run Code Online (Sandbox Code Playgroud) 谁能解释为什么下面的代码会编译,但如果我注释掉一行,那么它不会,即使代码本质上在做同样的事情?
struct OtherStruct {
x: i32,
}
struct Inner {
blah: i32,
vector: Vec<OtherStruct>
}
struct Outer {
inner: Inner,
}
impl Inner {
pub fn set_blah(&mut self, new_val : i32) {
self.blah = new_val;
}
}
fn main() {
let mut outer = Outer {
inner: Inner {
blah: 10,
vector: vec![
OtherStruct { x: 1 },
OtherStruct { x: 2 },
OtherStruct { x: 3 },
OtherStruct { x: 4 },
OtherStruct { x: 5 },
]
} …Run Code Online (Sandbox Code Playgroud) 在许多情况下,许多成员函数可以指定为“const” - 它们不会修改类的任何数据成员......几乎:它们会锁定/解锁类互斥锁。在这种情况下,指定互斥锁“可变”是一个好习惯吗? ...否则,将无法指定 get_a()、get_b()、get_c()、get_d() 'const'。
--
仅举一个例子。假设“example”是一个线程安全类,并且 m_mutex 保护其 get_a()、get_b()、get_c()、get_d() 不会修改的共享资源:
#include <mutex>
class example
{
public:
size_t get_a(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() + a;
};
size_t get_b(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() * 2 + a + b;
};
size_t get_c(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() * 4 + a + b;
};
size_t get_d(void) const {
std::lock_guard lck(m_mutex);
return m_str.length() * 8 + a;
};
void modify_something() {
std::lock_guard lck(m_mutex);
if …Run Code Online (Sandbox Code Playgroud) 示例代码可以在下面或godbolt上找到。假设我们有 4 个班级:
S<T>:持有数据成员。
SCtor<T>:持有数据成员并具有模板构造函数。
SCtorMutable<T>:持有可变数据成员并具有模板构造函数。
SCtorDefault<T>:持有一个成员,有一个模板构造函数,有默认的复制/移动构造函数和默认的复制/移动赋值运算符。
所有编译器都同意这 4 个类是可以简单复制的。
如果有一个简单的包装类W<T>将上述任何一个类作为数据成员。包装类W<S...<T>>仍然是可简单复制的。
如果有另一个包装类WMutable<T>将上述类中的任何一个保存为可变数据成员。
WMutable<S...<T>>是可以简单复制的。WMutable<S<T>>是可以复制的。WMutable<SCtor...<T>>不是可简单复制构造的,因此也不是可简单复制的。WMutable<S<T>>是可以简单复制的。WMutable<SCtor...<T>>不是可简单复制构造的,而是可简单复制的。应该WMutable<T>是可以简单复制的吗?
#include <type_traits>
#include <utility>
template<typename T>
struct S {
T m_t;
};
template<typename T>
struct SCtor {
T m_t;
template<typename... U>
SCtor(U&&... u): m_t(std::forward<U>(u)...) {}
};
template<typename T>
struct SCtorMutable {
mutable T m_t;
template<typename... U> …Run Code Online (Sandbox Code Playgroud) c++ mutable copy-constructor language-lawyer trivially-copyable