C++とRustを比較する
C++やってるけど、「Rustって安全だよ」って言われて興味を持った人向け。
用語はC++視点で。
関数に文字列を渡す
C++
main.cpp
#include <iostream>
void say(std::string str){
std::cout << "say: " << str << std::endl;
}
int main()
{
auto str = "hello";
say(str);
std::cout << "main: " << str << std::endl;
}
Output
say: hello
main: hello
Rust
main.rs
fn say(str: String){
println!("say: {}", str);
}
fn main() {
let str = String::from("hello");
say(str);
println!("say: {}", str);
}
error[E0382]: borrow of moved value: str
--> src/main.rs:10:25
|
8 | let str = String::from("hello");
| --- move occurs because `str` has type `std::string::String`, which does not implement the `Copy` trait
9 | say(str);
| --- value moved here
10 | println!("say: {}", str);
| ^^^ value borrowed here after move
Rustでは参照ではない値に渡すと所有権が移動する(say呼び出しの時点でmainではstrが使えなくなる)
Rustに黙らせるコード(参照で渡す)
main.rs
fn say(str: &String){
println!("say: {}", str);
}
fn main() {
let str = String::from("hello");
say(&str);
println!("say: {}", str);
}
Rustに黙らせるコード(所有権を返してもらう)
Rustは代入時に文字列を勝手に再確保&コピーしたりしません。
main.rs
fn say(str: String) -> String{
println!("say: {}", str);
str
}
fn main() {
let str = String::from("hello");
let str = say(str); //シャドーイングと言って、同名で上書きできる
println!("say: {}", str);
}
逆にRustっぽいことを、C++で書いてみる
所有権を1つに限定する(C++11以上)
main.cpp
#include <iostream>
#include <memory>
#include <utility>
std::unique_ptr<std::string> say(std::unique_ptr<std::string> str){
std::cout << "say: " << *str << std::endl;
return str;
}
int main()
{
std::unique_ptr<std::string> str(new std::string("hello"));
auto str2 = say(std::move(str));
std::cout << "str@main: " << str << std::endl;
//コメントアウトしないと落ちます
//std::cout << "*str@main: " << *str << std::endl;
std::cout << "*str2@main: " << *str2 << std::endl;
return 0;
}
Output
say: hello
str@main: 0x0
*str2@main: hello
C++では
- unique_ptrを使っても、コメントアウトした行のようにアクセスが可能、そして死ぬ