我发现了有趣的行为。
在 String
上调用 default
比在空 &str
上调用 to_string
多一条指令>。为什么?
pub fn string_default() -> String {
Default::default()
}
pub fn string_to_string() -> String {
"".to_string()
}
example::string_default:
mov rax, rdi
mov rcx, qword ptr [rip + .L__unnamed_1]
xorps xmm0, xmm0
movups xmmword ptr [rdi + 8], xmm0
mov qword ptr [rdi], rcx
ret
example::string_to_string:
mov rax, rdi
xorps xmm0, xmm0
movups xmmword ptr [rdi + 8], xmm0
mov qword ptr [rdi], 1
ret
.L__unnamed_1:
.asciz "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
UPD:构建配置文件“发布”
UPD (2):在 rust 1.52.0 之前,两个函数的汇编代码是相同的(4 条指令)。在 1.51.0 和更早版本中,mov qword
出现在 xorps
之前。
最佳答案
&str.to_string()
通过调用 &[u8]::to_owned( )
依次调用 &[u8]::to_vec()
并最终调用 RawVec::with_capacity_in
。
String::new()
和 String::default()
通过 Vec::new() 创建
内部包装 Vec
RawVec::SELF
,一个常量值。
您可以将示例简化为
fn slice_to_vec() -> Vec<u8> {
let b: &[u8] = &[];
let v = b.to_vec();
}
// example::slice_to_vec:
// mov rax, rdi
// mov qword ptr [rdi], 1
// xorps xmm0, xmm0
// movups xmmword ptr [rdi + 8], xmm0
// ret
对比
pub fn vec() -> Vec<u8> {
Vec::new()
}
// example::vec:
// mov rax, rdi
// mov rcx, qword ptr [rip + .L__unnamed_1]
// mov qword ptr [rdi], rcx
// xorps xmm0, xmm0
// movups xmmword ptr [rdi + 8], xmm0
// ret
//
// .L__unnamed_1:
// .asciz "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
我无法解释为什么会发生这种情况,但是 1.52 发生在 upgrade the LLVM version 上由 Rust 使用,所以也许这改变了生成的程序集。
关于assembly - 为什么要为默认字符串多一条汇编程序指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70071588/