[解決済み] 関数の引数として、文字列(&String)、Vec(&Vec)、ボックス(&Box)への参照を受け取ることは、なぜ推奨されないのですか?
質問
を受け取るRustコードを書きました。
&String
を引数として与えます。
fn awesome_greeting(name: &String) {
println!("Wow, you are awesome, {}!", name);
}
への参照を取り込むコードも書きました。
Vec
または
Box
:
fn total_price(prices: &Vec<i32>) -> i32 {
prices.iter().sum()
}
fn is_even(value: &Box<i32>) -> bool {
**value % 2 == 0
}
しかし、このようなやり方は良くないという意見もいただきました。なぜダメなのでしょうか?
解決方法は?
TL;DR: 代わりに
&str
,
&[T]
または
&T
を使用することで、より汎用的なコードが可能になります。
-
を使用する主な理由の1つは
String
またはVec
またはVec
. -
を受け付ける。
String
,&String
または&Vec
また が必要です。 は、関数を呼び出す前にヒープ上に確保されていなければなりません。を受け入れると&Box
は文字列リテラル(プログラムデータ内に保存)を許可し&str
または&[T]
は、スタックに確保された配列や変数を使用できます。不要なアロケーションはパフォーマンスの低下につながります。これは通常、これらのメソッドをテストの中で呼び出そうとすると、すぐにバレてしまいます。&T
メソッドを使用します。main
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
-
もう一つのパフォーマンスに関する考慮点は
is_even(&Box::new(42))
,&String
と&Vec
を参照する必要があるため、不必要なインダイレクトのレイヤーを導入してしまいます。&Box
を取得するために&String
で、2回目のデリファレンスを行って、最終的にString
.
代わりに
文字列スライス
(
&str
), a
スライス
(
&str
)、あるいは単なる参照(
&[T]
). A
&T
,
&String
または
&Vec<T>
は自動的に強制されます (via
デレフコークション
) を
&Box<T>
,
&str
または
&[T]
それぞれ
&T
fn awesome_greeting(name: &str) {
println!("Wow, you are awesome, {}!", name);
}
fn total_price(prices: &[i32]) -> i32 {
prices.iter().sum()
}
これで、これらのメソッドをより広い範囲の型を使って呼び出すことができるようになりました。例えば
fn is_even(value: &i32) -> bool {
*value % 2 == 0
}
は、文字列リテラル (
awesome_greeting
)
または
割り当てられた
"Anna"
.
String
は、配列への参照で呼び出すことができます (
total_price
)
または
割り当てられた
&[1, 2, 3]
.
の項目を追加したり削除したりしたい場合は、以下のようにします。
Vec
または
String
を取ることができます。
ミュータブルリファレンス
(
Vec<T>
または
&mut String
):
&mut Vec<T>
fn add_greeting_target(greeting: &mut String) {
greeting.push_str("world!");
}
スライスに特化した場合、スライスを受け取るために
fn add_candy_prices(prices: &mut Vec<i32>) {
prices.push(5);
prices.push(25);
}
または
&mut [T]
. これにより、スライス内の特定の値を変異させることができますが、スライス内のアイテムの数を変更することはできません(つまり、文字列に対して非常に制限されます)。
&mut str
fn reset_first_price(prices: &mut [i32]) {
prices[0] = 0;
}
関連
-
[解決済み] なぜパスワードにはStringではなくchar[]が好まれるのですか?
-
[解決済み] なぜlist.join(string)ではなくstring.join(list)なのでしょうか?
-
[解決済み] Stringでswitch文が使えないのはなぜですか?
-
[解決済み] 関数名を文字列として取得するには?
-
[解決済み] Java の String の hashCode() では、なぜ 31 が乗数として使われるのですか?
-
[解決済み] Bash関数から文字列値を返す方法
-
[解決済み] C#では、なぜStringは値型のように動作する参照型なのですか?
-
[解決済み] 文字列中の一部の文字を別の文字に置き換える
-
[解決済み】ある値とその値への参照を同じ構造体に格納できないのはなぜですか?
-
[解決済み] SwiftでNSDataから文字列を初期化する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
パイソンホワイトシステム実践プロジェクト200例(ソースコード付き)、練習が大幅にパイソン(Kunpengプログラミング - Pythonの教育新種)のレベルを向上させることができます。
-
[解決済み] Groovyの複数行のStringの何が問題なのですか?
-
[解決済み] YAML の文字列を複数行に渡って分割するには?
-
[解決済み] Bashで部分文字列を抽出する
-
[解決済み] grepを使ってフォルダ内の単語を検索するにはどうすればよいですか?
-
[解決済み] SwiftでIntをStringに変換する
-
[解決済み] 余分なスペースを含む複数行の文字列(インデントが保持される)
-
[解決済み] 文字列中の一部の文字を別の文字に置き換える
-
[解決済み] Goにはstartswith,endswith関数がない?
-
[解決済み] 文字列のすべての並べ換えのリストを生成する