理解Go语言struct的内存对齐
📅 2020-08-10
1.为什么要内存对齐? #
先来看一下字长的概念。字长是CPU的主要技术指标之一,指的是CPU一次能并行处理的二进制位数,通常CPU的字长为4字节(32位)、8字节(64位)。 CPU在访问内存时,并不是逐个字节访问的,而是以字长为单位访问。这么做的目的是为了减少CPU访问内存的次数,例如对于64位CPU,一次读取16字节数据只需要读取2次。
...先来看一下字长的概念。字长是CPU的主要技术指标之一,指的是CPU一次能并行处理的二进制位数,通常CPU的字长为4字节(32位)、8字节(64位)。 CPU在访问内存时,并不是逐个字节访问的,而是以字长为单位访问。这么做的目的是为了减少CPU访问内存的次数,例如对于64位CPU,一次读取16字节数据只需要读取2次。
...原子操作(atomic operation)是指不可分割且不可中断的一个或一系列操作,在并发编程中需要由CPU层面做出一些保证,让一系列操作成为原子操作。 一个原子操作从开始到结束可以是一个操作步骤,也可以包含多个操作步骤,这些步骤的顺序不可以被打乱,执行过程也不会被其他机制打断。
...今天来学习rust中的闭包。
rust中的闭包实际上是一个匿名函数,这个匿名函数可以被赋值给一个变量,可以作为参数传递给函数,可以作为函数返回值被返回,也可以为它实现某个trait,使其表现出其他行为。 在rust中可以在一个地方创建闭包,然后在不同的上下文中执行闭包运算。不同于函数,闭包允许捕获调用者作用域中的变量。
...昨天学习了Rust中与借用数据相关的三个trait: Borrow
, BorrowMut
和ToOwned
。
理解了这三个trait之后,今天来学习Rust中能够实现写时克隆的智能指针Cow<'a B>
。
Cow是Rust提供的用于实现写时克隆(Clone on write)的智能指针。
...今天学习Rust中与借用数据相关的三个trait: Borrow
, BorrowMut
和ToOwned
。
这三个trait在Rust标准库module std::borrow
中。
std:borrow
是Rust标准库中用于处理借用数据的moudle。这个module中除了Borrow, BorrowMut, ToOwned三个trait
外,还有一个Cow
enum。不过今天我们先只学习这三个trait。
今天来学习Rust中的slice类型。
为什么Rust会提供slice类型呢?
Rust中的借用(Borrow语义)可以将一个值在其所有权不发生转移的情况下,借给其他变量使用,借用通过创建引用来实现,Rust中创建引用的行为被称为借用。
但对于常用的集合类型例如Vec<T>
, String
(String的底层是Vec<u8>
),这些集合类型的引用类型&Vec<T>
, &String
,引用的将是整个集合的内容。
今天来学习rust中的ref
关键字。
先看下面的例子。
例1:
1
2#[derive(Debug)]
3enum HttpMethod {
4 Get(Get),
5 Post(Post),
6}
7
8#[derive(Debug)]
9struct Get {
10 url: String,
11}
12
13#[derive(Debug)]
14struct Post {
15 url: String,
16 body: Vec<u8>,
17}
18
19 fn main() {
20 let method = HttpMethod::Get(Get{
21 url: String::from("https://google.com"),
22 });
23
24 match method {
25 HttpMethod::Get(get) => println!("send get reuqest: {:?}", get),
26 HttpMethod::Post(post) => println!("send post reuqest: {:?}", post),
27 }
28
29 println!("{:?}", method); // 编译错误: borrow of partially moved value: `method`
30
31 }
上面例1中在使用match表达式进行模式匹配时,在执行第25行或26行时method会发生部分移动(partially moved),根据rust所有权规则中的Move语义,method将失去所有权,因此在第29行无法再使用method变量,报了编译错误。
...昨天我们学习了AsRef和AsMut两个trait,使用这两个trait可以实现引用到引用的转换:
U
实现了AsRef<T>
,则as_ref可以实现&U
到&T
的转换U
实现了AsMut<T>
,则as_ref可以实现从&U
到&mut T
的转换T
实现了AsRef<U>
,那么&T
就实现了AsRef<U>
T
实现了AsRef<U>
,那么&mut T
就实现了AsRef<U>
T
实现了AsMut<U>
,那么&mut T
就实现了AsMut<U>
到目前为止我们已经学习了Rust标准库中的11个常用的trait:
...昨天我们学习了Default trait,通过实现Default trait可以为类型提供缺省值。如果类型中的包含的其他类型都实现了Default trait,就可以通过derive宏#[derive(Default)]
来为类型自动实现Default trait,当然也可以手工实现Default trait。
继续学习Rust标准库中常用的trait,在开始今天的学习之前,先把前面已经学过的trait做一个简单的复习:
*v
。 实现Deref trait允许我们重载不可变引用的解引用运算符*
。 实现了Deref trait的智能指针可以被当做常规引用来对待,以便于访问其智能指针背后的数据。Rust为了提高在函数或方法传参时的便利性,提供了Deref强制转换(Deref coercion)功能。*v = 1;
。 实现DerefMut trait允许我们重载可变应用的解引用运算符*
。 实现了DerefMut trait的智能指针可以被当做常规可变引用来对待。因为DerefMut tait继承了Deref trait,因此也具有"Deref强制转换功能"。?
操作符自动实现下游到上游的错误转换。我们已经学习了FromStr, Deref, DerefMut, From, Into, TryFrom, TryInto这7个标准库中的trait,今天学习Default trait,使用Default trait可以为类型提供缺省值。
...