Rust
文章目录
差异
所有权
rust可以将不变所有权转为可变所有权
let a = String::from("str");
let mut b = a;
C++只能开发者自我约束, 在所有权移动前不去修改对象
const auto a = string("str");
auto b = move(a); // 降为复制
auto a = string("str");
auto b = move(a); // 有效移动
字符串
rust的字符串由长度和内容组成, 其中字符串不要求以0结尾.
let a = "str";
C++的字符串以内容和0结尾组成, 其中字符串一定以0结尾.
const char* a = "str";
类型结构
- | rust | 大小 | C++ | 大小 |
---|---|---|---|---|
引用类型 | &T &mut T | s | const T& T& | s |
指针类型 | *const T *mut T (unsafe) | s | const T* T* | s |
数组类型 | [T; N] | size_of::<T>() * N | T[N] | sizeof(T) * N |
切片类型 | &[T] &mut [T] &str &mut str | 2s | span<T> span<const T> span<char> span<const char> | 2s |
生命周期
函数返回的每一个引用类型和切片类型都需要从参数类型中获取生命周期, 如
fn foo(a: &str, b: &str) -> &str
一种选取是任选一个参数, 如取生命周期与a相同
fn foo<'a>(a: &'a str, b: &str) -> &'a str
另一种选取是取多个参数的最小值, 如取生命周期为a, b, c的最小值
fn foo<'a>(a: &'a str, b: &'a str, c: &'a str) -> &'a str
如不写明生命周期
- 当参数中只有一个引用类型/切片类型, 则取其生命周期
- 当参数中含
&self
或&mut self
, 则取其生命周期 - 报错
常量
const I: i32 = 3; constexpr int I = 3;
const S: &str = "3"; constexpr const char* S = "3";
基本类型
查询类型大小可用
use mem;
mem::size_of::<T>()
在说明大小时, 约定s为本机CPU位宽的字节数, 32位CPU下s=4, 64位CPU下s=8
基本类型 | 字面量后缀 | 字面量格式 | 大小 | 参考C++类型 |
---|---|---|---|---|
i8 | i8 | 1 | signed char | |
u8 | u8 | b'c' | 1 | unsigned char |
i16 | i16 | 2 | short | |
u16 | u16 | 2 | unsigned short | |
i32 | i32 (整数默认) | 4 | int | |
u32 | u32 | 4 | unsigned int | |
i64 | i64 | 8 | long long | |
u64 | u64 | 8 | unsigned long long | |
i128 | i128 | 16 | ||
u128 | u128 | 16 | ||
isize | isize | s | ssize_t | |
usize | usize | s | size_t | |
f32 | f32 | 4 | float | |
f64 | f64 (小数默认) | 8 | double | |
bool | true , false | 1 | bool | |
&str | "str" | 2s | const char* | |
char | 'c' | 4 | char32_t |
类型 | 不变切片类型 | 参考C++类型 | 不变切片参考C++类型 |
---|---|---|---|
&str | &str | const char[N] string_view | string_view |
String | &str | string | string_view |
[T; N] | &[T] | const T[N] span<const char, N> | span<const T> |
Vec<T> | &[T] | vector<T> | span<const T> |
类型 | 大小 | 注释 | 参考C++类型 |
---|---|---|---|
() | 0 | 默认返回类型 | void |
(i8, i8, i8) | 3 | tuple<int8_t, int8_t, int8_t> | |
(i8, i64) | 16 | 对齐 | tuple<int8_t, int64_t> |
struct T {} | 0 | struct T {} | |
struct T { a: i8, b: i8, c: i8 } | 3 | struct T { int8_t a; int8_t b; int8_t c; } | |
struct T { a: i64, b: i8 } | 16 | 对齐 | struct T { int64_t a; int8_t b; } |
enum T {} | 0 | class enum T {} | |
enum T { E1, E2 } | 1 | class enum T { E1, E2 } | |
enum T { E1(f32), E2(u8) } | 8 | variant<float, uint8_t> |
构造类型
构造新类型
struct NewType(T); struct NewType { T inner; };
struct NewType : T { using T::T; };
enum class NewType : T {};
类型别名
type TypeAlias = T; using TypeAlias = T;
typedef T TypeAlias;
template<typename T>
type TypeAlias<T> = U<T>; using TypeAlias = U<T>;
String
let s = "Hello"; const char* s = "Hello";
let s = String::new(); const auto s = string();
let mut s = String::new(); auto s = string();
s.push_str("bar"); s.append("bar");
let s = String::from("Hello"); const auto s = string("Hello");
let slice = &s[0..5]; auto slice = span(s.cbegin(), s.cbegin() + 5);
let mut s = String::from("Hello"); auto s = string("Hello");
let slice = &mut s[0..5]; auto slice = span(s.begin(), s.begin() + 5);
let slice = &s[0..5]; auto slice = span(s.cbegin(), s.cbegin() + 5);
let s1 = String::from("Hello"); auto s1 = string("Hello");
let s2 = String::from(", world"); const auto s2 = string(", world");
let s3 = s1 + &s2; const auto s3 = move(s1) + s2;
let s = format!("{}-{}", s2, s3); const auto s = format("{}-{}", s2, s3);
Vec
let v = vec![1, 2, 3]; const auto v = vector<int>{1, 2, 3};
let first = &v[0]; auto& first = v[0];
let mut v = vec![1, 2, 3]; auto v = vector<int>{1, 2, 3};
v.push(4); v.emplace_back(4);
let first = &v[0]; const auto& first = v[0];
let v = vec![1, 2, 3]; const auto v = vector<int>{1, 2, 3};
for i in &v { for (auto& i in v) {
println!("{}", i); cout << i << endl;
} }
let mut v = vec![1, 2, 3]; auto v = vector<int>{1, 2, 3};
for i in &mut v { for (auto& i in v) {
*i += 1; i += 1;
} }
HashMap
let mut scores = HashMap::new(); auto scores = unordered_map<string, int>();
scores.insert(String::from("Blue"), 10); scores["Blue"] = 10;
let team_name = String::from("Blue"); const auto team_name = string("Blue");
let score = scores.get(&team_name); const auto score = scores.find(team_name);
if let Some(score) = score { if (score != scores.end()) {
println!("{}", score); cout << score->second << endl;
} }
for (key, value) in &scores { for (const auto& [key, value] : scores) {
println!("{}: {}", key, value); cout << key << ": " << value << endl;
} }
File
let f = File::open("hello.txt"); FILE* f = fopen("hello.txt", "rb");
let mut f = match f { if (!f) {
Ok(file) => file, return;
Err(e) => return }
};
注: rust一般用?
处理Result
类型的值, 示例不是最佳实践.
泛型
template<typename T>
fn max<T>(list: &[T]) -> T { T max(span<const T> list) {
let mut m = list[0]; T m = list[0];
for &item in list { for (auto& item : list) {
if item > m { if (item > m) {
m = item; m = item;
} }
} }
m return m;
} }
C++的T可以是不完整类型, rust的T默认是Sized, 可确定大小的
template<typename T>
fn f<T: ?Sized>() {} void f() {}
template<typename T, size_t = sizeof(T)>
fn f<T>() {} void f() {}
Trait
编译时多态
template<typename T>
trait Summary { concept Summary = requires(T const& t) {
summarize_author(t);
summarize(t);
}
fn author(&self) -> String; string author(auto const& self);
fn summarize(&self) -> String { string summarize(auto const& self) {
format!("(Read more from {}...)", return format("(Read more from {}...)",
self.author()) author(self));
} }
}
struct Tweet { struct Tweet {
pub username: String, string username;
pub content: String, string content;
pub reply: bool, bool reply;
pub retweet: bool, bool retweet;
} };
impl Summary for Tweet { template<>
fn author(&self) -> String { string author<Tweet>(Tweet const& self) {
format!("@{}", self.username) return "@" + self.username;
} }
}
fn main() { int main() {
let tweet = Tweet { auto tweet = Tweet {
username: String::from("ebooks"), .username = "ebooks",
content: String::from("content"), .content = "content",
reply: false, .reply = false,
retweet: false, .retweet = false,
}; };
println!("1 new tweet: {}", cout << "1 new tweet: "
tweet.summarize()); << summarize(tweet) << endl;
} }
template<Summary T>
fn notify(item: &impl Summary) { void notify(T const& item) {
println!("Breaking news! {}", cout << "Breaking news! "
item.summarize()); << summarize(item) << endl;
} }
template<typename T, typename U>
fn some_function<T, U>(t: &T, u: &U) -> i32 int some_function(T const& t, U const& u)
where T: Display + Clone, requires Display<T> && Clone<T> &&
U: Clone + Debug Clone<U> && Debug<U>
{ {
template<Summary T = Tweet>
fn returns_summarizable() -> impl Summary { T returns_summarizable() {
Tweet { return Tweet {
username: String::from("ebooks"), .username = "ebooks",
content: String::from("content"), .content = "content",
reply: false, .reply = false,
retweet: false, .retweet = false,
} };
} }
运行时多态
pub trait Draw { struct Draw {
fn draw(&self); virtual draw() const = 0;
} };
pub struct Screen { struct Screen {
pub components: Vec<Box<dyn Draw>> vector<unique_ptr<Draw>> components;
}
impl Screen {
pub fn run(&self) { void run() const {
for component in self.components.iter() { for (const auto& component : components) {
component.draw(); component->draw();
} }
} }
} };
pub struct Button { struct Button : public Draw {
pub width: u32, uint32_t width;
pub height: u32, uint32_t height;
pub label: String string label;
}
impl Draw for Button {
fn draw(&self) { void darw() const override {
} }
} };
函数
fn f() -> ! {} [[noreturn]] void f() {}
注: C++的[[noreturn]]
非强制约束
Lambda/闭包/匿名函数
let f = |a: i32, b: i32| -> i32 { a }; const auto f = [](int a, int b) -> int { return a; };
let f = |a, b| { a }; const auto f = [](auto a, auto b) { return a; };
let f = |a| a; const auto f = [](auto a) { return a; };
注: rust的写法得到的是函数, 参数类型确定, 而C++的写法得到的是函数模板, 但亦可手动确定参数类型.
let s = String::from("Hello"); auto s = string("Hello");
let f = |a| s.len() + a; const auto f = [&](auto a) { return s.length() + a; };
let f = move |a| s.len() + a; const auto f = [s = move(s)](auto a) { return s.length() + a; };
let mut f = move |a| s.push_str(a); auto f = [s = move(s)](string_view a) mutable { s.append(a); };
模式匹配
字面量
let x = 1; auto x = 1;
match x { switch (x) {
1 => {}, case 1: { break; }
2 => {}, case 1: { break; }
_ => {}, default: { break; }
} }
枚举
let x = Some(5); auto x = optional(5);
let y = 10; auto y = 10;
match x {
Some(50) => {}, if (x && *x == 50) {}
Some(y) => {}, else if (x && *x == y) {}
_ => {}, else {}
}
多模式
let x = 1; auto x = 1;
match x { switch (x) {
1 | 2 => {}, case 1: case 2: { break; }
3 => {}, case 3: { break; }
_ => {} default: { break; }
} }
区间匹配
let x = 'c'; auto x = 'c';
match x {
'a'..'j' => {}, if ('a' <= x && x <= 'j') {}
'k'..'z' => {}, else if ('k' <= x && x <= 'z') {}
_ => {} else {}
}
解构
let (x, y) = (1, 2); auto [x, y] = make_tuple(1, 2);
struct Point { struct Point {
x: i32, int x;
y: i32, int y;
} };
let Point { x, y } = Point { 2, 3 }; auto [x, y] = Point { 2, 3 };
match p {
Point { x, y: 0 } => {}, if (p.y == 0) {}
Point { x: 0, y } => {}, else if (p.x == 0) {}
Point { x, y } => {}, else {}
}
enum Message {
Quit, struct Quit {};
Move { x: i32, y: i32 }, struct Move { int x; int y; };
Write(String), struct Write { string val };
ChangeColor(i32, i32, i32) struct ChangeColor { tuple<int, int, int> val; };
} struct Message : variant<Quit, Move, Write, ChangeColor> {
using variant<Quit, Move, Write, ChangeColor>::variant;
};
let m = Message::ChangeColor(0, 1, 2); Message m = ChangeColor { { 0, 1, 2 } };
match m { visit([](auto& val) {
Message::Quit => { if constexpr (is_assignable_v<decltype(val), Quit>) {
}, }
Message::Move { x, y } => { else if constexpr (is_assignable_v<decltype(val), Move>) {
auto [x, y] = val;
}, }
Message::Write(text) => { else if constexpr (is_assignable_v<decltype(val), Write>) {
auto text = move(val.val);
}, }
Message::ChangeColor(r, g, b) => { else {
static_assert(is_assignable_v<decltype(val), ChangeColor>);
auto [r, g, b] = val.val;
}, }
} }, m);
迭代器
let mut v1 = vec![1, 2, 3]; auto v1 = vector<int>{1, 2, 3};
for val in v1 {} for (auto val : v1) {}
for val in &v1 {} for (const auto& val : v1) {}
for val in &mut v1 {} for (auto& val : v1) {}
for val in v1.iter() {} for (auto& val : span(v1.cbegin(), v1.cend())) {}
for val in v1.iter_mut() {} for (auto& val : span(v1.begin(), v1.end())) {}
let v1 = vec![1, 2, 3]; const auto v1 = vector<int>{1, 2, 3};
let mut it = v1.iter(); auto it = v1.begin(), itEnd = v1.end();
assert_eq!(it.next(), Some(&1)); assert(it != itEnd); assert(*it == 1);
assert_eq!(it.next(), Some(&2)); assert(++it != itEnd); assert(*it == 2);
assert_eq!(it.next(), Some(&3)); assert(++it != itEnd); assert(*it == 3);
assert_eq!(it.next(), None); assert(++it == itEnd);
struct Counter { struct Iter {
count: i32, using difference_type = ptrdiff_t;
} using value_type = int;
value_type count;
impl Counter { bool operator==(Iter const& other) const {
fn new() -> Counter { return count == other.count;
Counter { count: 0 } }
} Iter& operator++() {
} ++count;
return *this;
impl Iterator for Counter { }
type Item = i32; void operator++(int) {
++*this;
fn next(&mut self) -> Option<Self::Item> { }
if self.count < 5 { value_type operator*() const {
self.count += 1; return count;
Some(self.count) }
} else { };
None struct Counter {
} static Iter begin() { return Iter { 0 }; }
} static Iter end() { return Iter { 5 }; }
} };
fn main() { int main() {
let cnt = Counter::new(); auto cnt = Counter();
for val in cnt { for (auto val : cnt) {
println!("{}", val); cout << val << endl;
} }
} }
let mut v1 = vec![1, 2, 3]; auto v1 = vector<int>{1, 2, 3};
let total = v1.iter().sum(); const auto total = accumulate(v1.begin(), v1.end(), 0);
let m = v1.iter().map(|x| auto m = v1 | views::transform([](auto x) {
x + 1 return x + 1;
); });
let v2: Vec<_> = v1.iter().map(|x| auto v2_views = v1 | views::transform([](auto x) {
x + 1 return x + 1;
).collect(); });
auto v2 = vector<int>(v2_views.begin(), v2_views.end());
let sum: i32 = Counter::new() auto ints = views::zip(Counter(), Counter() | views::drop(1))
.zip(Counter::new().skip(1)) | views::transform([](auto ab) {
.map(|(a, b)| a * b) return get<0>(ab) * get<1>(ab);
}) | views::filter([](auto x) {
.filter(|x| x % 3 == 0) return x % 3 == 0;
});
.sum(); auto sum = accumulate(ints.being(), ints.end(), 0);
智能指针
- unique
let b = Box::new(5); auto b = make_unique<int>(5);
- 不变shared
let b = Rc::new(5); auto b = make_shared<const int>(5);
let c = Rc::clone(&b); auto c = b;
let d = b.clone(); auto d = b;
let cnt = Rc::strong_count(&d); auto cnt = d.use_count();
- 可变shared
let b: RefCell<Vec<String>> = RefCell::new(vec![]); auto b = make_shared<vector<string>>();
b.borrow_mut().push("Hello"); b->emplace_back("Hello");
b.borrow().len(); b->size();
析构函数
struct Data { struct Data {
data: String, string data;
}
impl Drop for Data {
fn drop(&mut self) { ~Data() {
} }
} };
注: 可用mem::drop
将对象提前销毁, C++中只能使用}
隐式销毁.
线程
let t = thread::spawn(|| { auto t = thread([] {
thread::sleep( this_thread::sleep_for(
Duration::from_millis(1000) chrono::millisceonds(1000);
); );
}); });
t.join().unwrap(); t.join();
let v = vec![1, 2, 3]; auto v = vector<int>{1, 2, 3};
let t = thread::spawn(move || { auto t = thread([v = move(v)] {
for i in &v {} for (const auto& i : v) {}
}); });
线程通信
管道
send recv用法
let (tx, rx) = mpsc::channel();
let t = thread::spawn(move || {
tx.send(String::from("hi")).unwrap();
});
let s = rx.recv().unwrap();
迭代用法
let (tx, rx) = mpsc::channel();
let t = thread::spawn(move || {
let vals = vec![
String::from("a"), String::from("b"), String::from("c"),
];
for val in vals {
tx.send(val).unwrap();
};
});
for s in rx {}
多sender
let (tx1, rx) = mpsc::channel();
let tx2 = tx1.clone();
thread::spawn(move || {
tx1.send(String::from("a"));
});
thread::spawn(move || {
tx2.send(String::from("b"));
});
信号量
auto num = 5;
let m = Mutex::new(5); auto m = mutex();
{ {
let mut num = m.lock().unwrap(); auto guard = lock_guard<mutex>(m);
*num = 6; num = 6;
} }
注: Mutex = tuple<T, mutex>
let cnt = Arc::new(Mutex::new(0));
for _ in 0..10 {
let cnt = Arc::clone(&cnt);
thread::spawn(move || {
let mut num = cnt.lock().unwrap();
*num += 1;
});
}
注: Arc类同Rc, 其中计数器用atomic
- | 可变 | 不变 |
---|---|---|
单线程 | RefCell | Rc |
多线程 | Mutex | Arc |
C交互
导入C (unsafe)
extern "C" { extern "C" {
fn abs(input: i32) -> i32; int abs(int input);
} }
fn main() { int main() {
unsafe {
abs(233); abs(233);
}
} }
导出C
#[no_mangle]
pub extern "C" fn f() { extern "C" void f() {
} }
联合体 (unsafe)
#[repr(C)]
union MyUnion { union MyUnion {
f1: u32, uint32_t f1;
f2: f32, float f2;
} };
let u = MyUnion { f1: 1 }; auto u = MyUnion { .f1 = 1 };
let f = unsafe { u.f1 }; auto f = u.f1;
unsafe {
match u {
MyUnion { f1: 10 } => {} if (u.f1 == 10) {}
MyUnion { f2 } => {} else {}
}
}