Rust 跨迭代移动不可复制的结构

Rust 跨迭代移动不可复制的结构,rust,Rust,我试图访问for循环中的变量。我无法在结构上实现复制,因为它包含字符串。我如何在迭代中使用变量 编译时出现错误E0382。当我查看有关错误的Rust文档时,他们提到使用引用计数来解决问题。这是我的唯一解决办法吗 #[derive(Clone)] struct InputParser { args: Vec<String>, current: String, consumed_quote: bool, } impl InputParser { pub

我试图访问
for
循环中的变量。我无法在结构上实现
复制
,因为它包含
字符串
。我如何在迭代中使用变量

编译时出现错误E0382。当我查看有关错误的Rust文档时,他们提到使用引用计数来解决问题。这是我的唯一解决办法吗

#[derive(Clone)]
struct InputParser {
    args: Vec<String>,
    current: String,
    consumed_quote: bool,
}

impl InputParser {
    pub fn parse(input: String) -> Vec<String> {
        let parser = InputParser {
            args: Vec::new(),
            current: String::new(),
            consumed_quote: false,
        };
        for c in input.chars() {
            match c {
                '"' => parser.consume_quote(),
                ' ' => parser.consume_space(),
                _ => parser.consume_char(c),
            }
        }
        parser.end();

        return parser.args;
    }

    pub fn consume_space(mut self) {
        if !self.consumed_quote {
            self.push_current();
        }
    }

    pub fn consume_quote(mut self) {
        self.consumed_quote = self.consumed_quote;
        if self.consumed_quote {
            self.push_current();
        }
    }

    pub fn consume_char(mut self, c: char) {
        self.current.push(c);
    }

    pub fn end(mut self) {
        self.push_current();
    }

    pub fn push_current(mut self) {
        if self.current.len() > 0 {
            self.args.push(self.current);
            self.current = String::new();
        }
    }
}
#[派生(克隆)]
结构输入分析器{
args:Vec,
当前:字符串,
引用:bool,
}
impl输入解析器{
pub fn parse(输入:字符串)->Vec{
让parser=InputParser{
args:Vec::new(),
当前:字符串::新(),
引用:false,
};
对于input.chars()中的c{
比赛c{
“”=>parser.consumer_quote(),
''=>parser.consumer_space(),
_=>解析器。使用字符(c),
}
}
parser.end();
返回parser.args;
}
pub fn消耗_空间(mut self){
如果!自我消费\u报价{
自推式电流();
}
}
pub fn消费报价(多个自身){
self.consumered\u quote=self.consumered\u quote;
如果自行消费(报价),{
自推式电流();
}
}
pub fn consumer_char(mut self,c:char){
自电流推力(c);
}
发布fn端(多个自身){
自推式电流();
}
pub fn推送电流(多个自身){
如果self.current.len()大于0{
自参数推送(自电流);
self.current=String::new();
}
}
}
我想在
for
循环的
迭代中访问
解析器

[如何]在迭代中移动[a]不可复制的结构

没有,至少不是很简单。一旦您将结构移动到函数,它就消失了。取回它的唯一方法是函数将其返回给您

相反,您很可能希望修改循环中的现有结构。您需要为此使用可变引用:

use std::mem;

#[derive(Clone)]
struct InputParser {
    args: Vec<String>,
    current: String,
    consumed_quote: bool,
}

impl InputParser {
    fn consume_space(&mut self) {
        if !self.consumed_quote {
            self.push_current();
        }
    }

    fn consume_quote(&mut self) {
        self.consumed_quote = self.consumed_quote;
        if self.consumed_quote {
            self.push_current();
        }
    }

    fn consume_char(&mut self, c: char) {
        self.current.push(c);
    }

    fn end(&mut self) {
        self.push_current();
    }

    fn push_current(&mut self) {
        if self.current.len() > 0 {
            let arg = mem::replace(&mut self.current, String::new());
            self.args.push(arg);
        }
    }
}

fn parse(input: String) -> Vec<String> {
    let mut parser = InputParser {
        args: Vec::new(),
        current: String::new(),
        consumed_quote: false,
    };
    for c in input.chars() {
        match c {
            '"' => parser.consume_quote(),
            ' ' => parser.consume_space(),
            _ => parser.consume_char(c),
        }
    }
    parser.end();

    parser.args
}

fn main() {}
我相信在这种情况下,API客观上会变得更糟糕。但是,在构建器中,您会经常看到这种样式。在这种情况下,方法往往链接在一起,因此您永远不会看到对变量的重新分配

[如何]在迭代中移动[a]不可复制的结构

没有,至少不是很简单。一旦您将结构移动到函数,它就消失了。取回它的唯一方法是函数将其返回给您

相反,您很可能希望修改循环中的现有结构。您需要为此使用可变引用:

use std::mem;

#[derive(Clone)]
struct InputParser {
    args: Vec<String>,
    current: String,
    consumed_quote: bool,
}

impl InputParser {
    fn consume_space(&mut self) {
        if !self.consumed_quote {
            self.push_current();
        }
    }

    fn consume_quote(&mut self) {
        self.consumed_quote = self.consumed_quote;
        if self.consumed_quote {
            self.push_current();
        }
    }

    fn consume_char(&mut self, c: char) {
        self.current.push(c);
    }

    fn end(&mut self) {
        self.push_current();
    }

    fn push_current(&mut self) {
        if self.current.len() > 0 {
            let arg = mem::replace(&mut self.current, String::new());
            self.args.push(arg);
        }
    }
}

fn parse(input: String) -> Vec<String> {
    let mut parser = InputParser {
        args: Vec::new(),
        current: String::new(),
        consumed_quote: false,
    };
    for c in input.chars() {
        match c {
            '"' => parser.consume_quote(),
            ' ' => parser.consume_space(),
            _ => parser.consume_char(c),
        }
    }
    parser.end();

    parser.args
}

fn main() {}

我相信这在客观上会使API在这种情况下变得更糟糕。但是,在构建器中,您会经常看到这种样式。在这种情况下,方法往往链接在一起,因此您永远不会看到对变量的重新分配。

为什么
parse
函数是InputParser实现的一部分?它不会返回InputParser也不接受自我参照。为什么要按值接受
self
fn end(mut self)
)到处都是?
self.consumered\u quote=self.consumered\u quote;
是一个非常可疑的行。谢谢你帮我省去了一些困惑,应该是
self.consumered\u quote=!self.consumered\u quote;
为什么
parse
函数是InputParser实现的一部分?它既不返回InputParser,也不接受自引用。你为什么要ng
self
按值(
fn-end(mut-self)
)到处都是?
self.consumered\u quote=self.consumered\u quote;
是一个非常可疑的行。谢谢你帮我省去了一些困惑,应该是
self.consumered\u quote=!self.consumered\u quote;
当前的
最好是作为
选项实现的,但我认为这取决于你所使用的语义如果区分空字符串和缺少的字符串很重要,那么当然,但是使用它的地方都会有麻烦。但是,如果您考虑对
选项::take
使用
选项
,请注意它是用
mem::replace
实现的!空
字符串
非常轻权重也是一样,只有几个指针大小的整数,没有堆分配。
mem::replace
没有什么可怕的地方。这在这里确实是有意义的。
current
不是更好地实现为一个
选项吗?@SirDarius可以工作,但我认为这取决于你想要的语义。如果区分一个空字符串和一个丢失的字符串,然后确定,但是使用它的地方都会有麻烦。但是,如果您正在考虑对
选项::take
使用
选项
,请注意它是用
mem::replace
实现的!空
字符串
也非常轻量级,只需几点r大小的整数,没有堆分配。
mem::replace
没有什么可怕的地方。这在这里确实有意义。