gpt4 book ai didi

rust - 有没有一种内存有效的方法来更改固有实现的行为?

转载 作者:行者123 更新时间:2023-12-03 11:35:27 26 4
gpt4 key购买 nike

有没有一种内存有效的方法来更改固有实现上的行为?目前,我可以通过存储许多函数指针来完成行为更改,然后由固有实现调用这些函数指针。我的困难在于,可能存在大量此类功能以及大量依赖于这些功能的对象,因此,我想减少使用的内存量。作为示例,请考虑以下代码:

// Holds the data for some process
struct MyData {
x: f64,
y: f64,
fns: MyFns,
}
impl MyData {
// Create a new object
fn new(x: f64, y: f64) -> MyData {
MyData {
x,
y,
fns: CONFIG1,
}
}

// One of our functions
fn foo(&self) -> f64 {
(self.fns.f)(self.x, self.y)
}

// Other function
fn bar(&self) -> f64 {
(self.fns.g)(self.x, self.y)
}
}

// Holds the functions
struct MyFns {
f: fn(x: f64, y: f64) -> f64,
g: fn(x: f64, y: f64) -> f64,
}

// Some functions to use
fn add(x: f64, y: f64) -> f64 {
x + y
}
fn sub(x: f64, y: f64) -> f64 {
x - y
}
fn mul(x: f64, y: f64) -> f64 {
x * y
}
fn div(x: f64, y: f64) -> f64 {
x / y
}

// Create some configurations
const CONFIG1: MyFns = MyFns {
f: add,
g: mul,
};
const CONFIG2: MyFns = MyFns {
f: sub,
g: div,
};

fn main() {
// Create our structure
let mut data = MyData::new(1., 2.);

// Check our functions
println!(
"1: x={}, y={}, foo={}, bar={}",
data.x,
data.y,
data.foo(),
data.bar()
);

// Change the functions
data.fns = CONFIG2;

// Print the functions again
println!(
"2: x={}, y={}, foo={}, bar={}",
data.x,
data.y,
data.foo(),
data.bar()
);

// Change a single function
data.fns.f = add;

// Print the functions again
println!(
"3: x={}, y={}, foo={}, bar={}",
data.x,
data.y,
data.foo(),
data.bar()
);
}
此代码允许通过编辑 foobar来更改 fg的行为。但是,它也不灵活。我宁愿使用装箱的特征对象 Box<dyn Fn(f64,f64)->f64,但是之后我无法创建一些默认配置(例如 CONFIG1CONFIG2),因为 Box不能用于创建常量对象。另外,如果我们有大量的函数和对象,我想为它们的实现共享内存。对于函数指针来说,这没什么大不了的,但是对于闭包来说,它却是。在这里,我们无法为配置创建常量 Rc来共享内存。最后,我们可以静态引用某个配置,这样可以节省内存,但是之后我们就无法更改各个功能。我宁愿遇到这样一种情况,在大多数情况下,我们为这些功能共享内存,但是有能力保留自己的内存并根据需要更改功能。
如果可以的话,我愿意提供更好的设计。最终,我想基于 foo内部以某种形式或另一种形式持有的函数在运行时更改 barMyData的行为。此外,我想提供一种在可能的情况下共享内存的方法,并且我们能够更改单个功能,而不仅仅是整个配置。

最佳答案

一个简单的dyn引用将在这里工作-它允许引用具有特定特征但类型仅在运行时已知的对象。
(这正是您想要的函数指针。将其视为每个函数都有其自己的特殊类型,但是属于Fn(f64,f64)->f64之类的特性。)
因此,您的结构可以定义为:

struct MyData<'a> {
x: f64,
y: f64,
f: &'a dyn Fn(f64, f64) -> f64,
g: &'a dyn Fn(f64, f64) -> f64,
}
(注意,您需要生命周期说明符 'a,以确保该引用的生命周期不短于结构本身。)
然后,您的展示次数可能像:
impl<'a> MyData<'a> {
// Create a new object
fn new(x: f64, y: f64) -> Self {
MyData {
x,
y,
f: &add, // f and g as in CONFIG1
g: &mul,
}
}

fn foo(&self) -> f64 {
(self.f)(self.x, self.y)
}

// etc...
}
根据您希望默认配置的工作方式,您可以将它们配置为更多固有函数(例如 fn to_config2(&mut self);),也可以仅使用函数指针创建单独的结构,然后具有将这些函数指针复制到 MyData结构中的函数。

关于rust - 有没有一种内存有效的方法来更改固有实现的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62523879/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com