2015-09-26 27 views
0

正如標題已經說過的,我試圖將一個&[&str]移動到一個線程中。嗯,其實,下面的代碼工作,但我有兩個問題是:將一個&[&str]移動到一個線程

  1. let args2: Vec<_> = args.iter().map(|arg| { arg.to_string() }).collect();似乎有點冗長的&[&str]轉換爲Vec<String>。這可以做到「更好」嗎?
  2. 如果我理解正確,字符串會被複制兩次:第一個是let cmd2let args2語句;然後通過在move關閉內移動它們。它是否正確?如果是這樣,可以用一個副本來完成嗎?

我所知道的thread::scoped,不過目前已被棄用。我也在編寫這個代碼來學習一些關於Rust的知識,所以關於「不可信」代碼的評論也是值得讚賞的。

use std::process::{Command,Output}; 
use std::thread; 
use std::thread::JoinHandle; 

pub struct Process { 
    joiner: JoinHandle<Output>, 
} 

impl Process { 
    pub fn new(cmd: &str, args: &[&str]) -> Process { 
     // Copy the strings for the thread 
     let cmd2 = cmd.to_string(); 
     let args2: Vec<_> = args.iter().map(|arg| { arg.to_string() }).collect(); 

     let child = thread::spawn(move || { 
      Command::new(cmd2).args(&args2[..]).output().unwrap_or_else(|e| { 
       panic!("Failed to execute process: {}", e) 
      }) 
     }); 
     Process { joiner: child } 
    } 
} 

回答

3

let args2: Vec<_> = args.iter().map(|arg| { arg.to_string() }).collect();似乎有點冗長轉換一個& [& STR]到A VEC。這可以做到「更好」嗎?

我不這麼認爲。有一些小的變化也可以工作(例如args.iter().cloned().map(String::from).collect();),但我想不出一個更好的。一個小問題是,使用to_string&str轉換爲String的效率不如使用String::fromto_owned

如果我理解正確的話,琴絃被複制兩次:第一次由設CMD2,讓args2報表;然後通過將它們移動到移動閉合內部。它是否正確?如果是這樣,可以用一個副本來完成嗎?

不,字符串只在您撥打to_string的地方複製。字符串不實現Copy,所以它們不會被隱式複製。如果您嘗試在移動到閉包後訪問這些字符串,則會出現編譯器錯誤。

+0

謝謝你'String :: from'。對於第二點,我首先明確地將字符串複製到'cmd2'和'args2'中,但是當它們被移入閉包時,它們是不是也被物理地複製到了線程堆棧中呢? – Garogolun

+0

@Garogolun那麼,矢量被複制,但這只是一個淺拷貝(即包含指針,長度和容量的結構)。矢量的內容不被複制。 – fjh

+0

線程可以訪問向量的內容。但是,如果'Process :: new'返回,則矢量及其內容會被破壞。那麼這不是不安全嗎? – Garogolun

相關問題