字符串是丢弃还是复制?

时间:2017-06-15 08:19:04

标签: rust ownership

我正在了解Rust的所有权。我的测试表明,在移动String个实例时,会在变量赋值中复制字符串文字。这是否意味着StringDrop而字符串文字为Copy

variable_assign_test.rs

// variable assign test,

// assign variable on stack to another,
fn test_stack_assign() {
    let x = 5;
    let y = x; // data duplicated on stack,
    println!("x = {}, y = {}", x, y); // it's ok,
}

// assign variable on heap to another,
fn test_heap_assign() {
    let s1 = String::from("hello");
    let s2 = s1;    // now s1 is invalid, should not use it any more,
    // println!("{}", s1); // this won't compile,
    println!("s2 = {}", s2); // it's ok,
}

fn test_tuple_assign() {
    let pa = (1, 2);
    let pb = pa;
    println!("pa = {:?}, pb = {:?}", pa, pb); // it's ok,

    // tuple that contains string literal,
    let name_monica = "monica";
    let monica = (11, name_monica);
    let monica2 = monica;
    println!("monica = {:?}, monica2 = {:?}", monica, monica2);

    // tuple that contains String instance,
    let name_eric = String::from("eric");
    let eric = (12, name_eric);
    let eric2 = eric; // eric is invalid now,
    // println!("eric = {:?}, eric = {:?}", eric, eric2); // this won't compile,
}

fn main() {
    test_stack_assign();
    test_heap_assign();
    test_tuple_assign();
}

使用rustc variable_assign_test.rs -o a.out进行编译并使用./a.out

运行

如果test_tuple_assign()的最后一行已取消注释,则变量value used here after move会收到错误eric

1 个答案:

答案 0 :(得分:10)

要清楚,所有不可变引用(&T)都是Copy,而可变引用(&mut T)只是移动。 &'static str,字符串文字的类型,只是&T的一个特例,是一个不可变引用,因此是Copy

另一方面,String实例是其内容的动态分配缓冲区的单个所有者。这可以防止它成为Copy(单个所有者)并要求它实现Drop(以释放动态分配的缓冲区)。

但是,具体而言,String并未直接实现Drop,而是围绕Vec<u8>的包装器,Drop本身实现Drop。行为完全相同,只是String Vec<u8>的实现是自动生成的,而function wp_corenavi() { global $wp_query, $wp_rewrite; $next = '<img src="'.get_template_directory_uri().'/assets/img/btn_next_01_pc.png"sizes="(max-width: 750px) 42px, 60px" srcset="'.get_template_directory_uri().'/assets/img/btn_next_01.png 85w,'.get_template_directory_uri().'/assets/img/btn_next_01_pc.png 60w,'.get_template_directory_uri().'/assets/img/btn_next_01_pc@2x.png 120w"alt="次の記事へ" />'; $prev = '<img src="'.get_template_directory_uri().'/assets/img/btn_prev_01_pc.png"sizes="(max-width: 750px) 40px, 58px" srcset="'.get_template_directory_uri().'/assets/img/btn_prev_01.png 81w,'.get_template_directory_uri().'/assets/img/btn_prev_01_pc.png 58w,'.get_template_directory_uri().'/assets/img/btn_prev_01_pc@2x.png 116w"alt="前の記事へ" />'; $pages = ''; $max = $wp_query->max_num_pages; if (!$current = get_query_var('paged')) $current = 1; $a['base'] = str_replace(999999999, '%#%', get_pagenum_link(999999999)); $a['total'] = $max; $a['current'] = $current; $total = 1; //1 - display the text "Page N of N", 0 - not display $a['mid_size'] = 2; //how many links to show on the left and right of the current $a['end_size'] = 1; //how many links to show in the beginning and end $a['prev_text'] = $prev; //text of the "Previous page" link $a['next_text'] = $next; //text of the "Next page" link $a['before_page_number'] = '<span class="pagination_elem">'; $a['after_page_number'] = '</span>'; $big = 999999999; // need an unlikely integer if ($max > 1) echo '<div id="js_pagination" class="wp-pagenavi">'; echo $pages . paginate_links($a); if ($max > 1) echo '</div>'; } 的实现是manually written