编译器可以对特征的方法进行默认实现的内联吗?
Can compiler do a default implementation's inlining of the trait's method?
我知道 trait 的方法没有主体,所以没有什么可以内联的。但是这样标记它的默认实现有什么意义吗?
trait Magnitude {
fn square_magnitude( &self ) -> f64;
#[inline]
fn magnitude( &self ) -> f64 {
self.square_magnitude().sqrt()
}
}
我是否需要重写整个方法体并用 #[inline]
标记这个 impl 的方法,而不是像上面那样只标记特征的方法?
如果我理解正确的话,你是在问两件事:
- 编译器会内联调用
magnitude
吗?
- 如果
square_magnitude
本身声明为 inline
,即使 square_magnitude
的代码,编译器是否能够在 magnitude
中内联对 square_magnitude
的调用在特征中不可用?
至于第一个,没有理由不能。至于第二个,答案是肯定的,编译器将能够内联这两个函数,因为在它生成代码时,这两个函数的源代码都是可用的。这可以在 disassembly:
中看到
trait Magnitude {
fn square_magnitude( &self ) -> f64;
#[inline]
fn magnitude( &self ) -> f64 {
self.square_magnitude().sqrt()
}
}
struct Vector { x: f64, y: f64 }
impl Magnitude for Vector {
#[inline]
fn square_magnitude (&self) -> f64 {
self.x*self.x + self.y*self.y
}
}
pub fn test (x: f64, y: f64) -> f64 {
let v = Vector { x: x, y: y };
v.magnitude()
}
使用 rustc v1.28.0 和选项编译 -O
:
example::test:
mulsd xmm0, xmm0
mulsd xmm1, xmm1
addsd xmm1, xmm0
xorps xmm0, xmm0
sqrtsd xmm0, xmm1
ret
impl Magnitude for Vector {
fn square_magnitude (&self) -> f64 {
self.x*self.x + self.y*self.y
}
}
生成:
<example::Vector as example::Magnitude>::square_magnitude:
movsd xmm1, qword ptr [rdi]
movsd xmm0, qword ptr [rdi + 8]
mulsd xmm1, xmm1
mulsd xmm0, xmm0
addsd xmm0, xmm1
ret
example::test:
mulsd xmm0, xmm0
mulsd xmm1, xmm1
addsd xmm1, xmm0
xorps xmm0, xmm0
sqrtsd xmm0, xmm1
ret
我知道 trait 的方法没有主体,所以没有什么可以内联的。但是这样标记它的默认实现有什么意义吗?
trait Magnitude {
fn square_magnitude( &self ) -> f64;
#[inline]
fn magnitude( &self ) -> f64 {
self.square_magnitude().sqrt()
}
}
我是否需要重写整个方法体并用 #[inline]
标记这个 impl 的方法,而不是像上面那样只标记特征的方法?
如果我理解正确的话,你是在问两件事:
- 编译器会内联调用
magnitude
吗? - 如果
square_magnitude
本身声明为inline
,即使square_magnitude
的代码,编译器是否能够在magnitude
中内联对square_magnitude
的调用在特征中不可用?
至于第一个,没有理由不能。至于第二个,答案是肯定的,编译器将能够内联这两个函数,因为在它生成代码时,这两个函数的源代码都是可用的。这可以在 disassembly:
中看到trait Magnitude {
fn square_magnitude( &self ) -> f64;
#[inline]
fn magnitude( &self ) -> f64 {
self.square_magnitude().sqrt()
}
}
struct Vector { x: f64, y: f64 }
impl Magnitude for Vector {
#[inline]
fn square_magnitude (&self) -> f64 {
self.x*self.x + self.y*self.y
}
}
pub fn test (x: f64, y: f64) -> f64 {
let v = Vector { x: x, y: y };
v.magnitude()
}
使用 rustc v1.28.0 和选项编译 -O
:
example::test:
mulsd xmm0, xmm0
mulsd xmm1, xmm1
addsd xmm1, xmm0
xorps xmm0, xmm0
sqrtsd xmm0, xmm1
ret
impl Magnitude for Vector {
fn square_magnitude (&self) -> f64 {
self.x*self.x + self.y*self.y
}
}
生成:
<example::Vector as example::Magnitude>::square_magnitude:
movsd xmm1, qword ptr [rdi]
movsd xmm0, qword ptr [rdi + 8]
mulsd xmm1, xmm1
mulsd xmm0, xmm0
addsd xmm0, xmm1
ret
example::test:
mulsd xmm0, xmm0
mulsd xmm1, xmm1
addsd xmm1, xmm0
xorps xmm0, xmm0
sqrtsd xmm0, xmm1
ret