を生成し、この質問は、最も確かに前に答えたが、ここでは、コードが多少異なっていると私はそれが重要だと思うので、私は重複としてそれを閉じていませんよ。あなたがあなたの関数を定義した方法
注:
fn combine(orig: &'a str) -> A<'a>
それが内部に正確限り提供文字列として生きるタイプA
の値を返すことを言います。しかし、関数の本体は、この宣言に違反:
let attr = &*(orig.to_string() + "suffix");
A {
some_attr: attr
}
は、ここでは、
orig
から入手
新しい
String
を構築し、それのスライスを取り、
A
の内側にそれを返すようにしてみてください。しかし、
orig.to_string() + "suffix"
のために作成された暗黙的な変数の存続期間は、厳密に入力パラメータの存続期間よりも短くなります。したがって、プログラムは拒否されます。
もう1つ、より実際的な方法は、to_string()
によって作成された文字列と連結がどこかに存在しなければならないことです。しかし、あなたはそれを借りて返すだけです。したがって、関数が終了すると、文字列は破棄され、返されたスライスは無効になります。これはまさにRustが防止する状況です。
pub struct A {
some_attr: String
}
たり、スライスまたは所有する文字列のいずれかを格納するのにstd::borrow::Cow
を使用することができます:最後の場合、あなたには
pub struct A<'a> {
some_attr: Cow<'a, str>
}
をこのあなたがA
内部String
を保存することができますいずれかを克服するために
関数は次のようになります。
fn combine(orig: &str) -> A<'static> {
let attr = orig.to_owned() + "suffix";
A {
some_attr: attr.into()
}
}
関数内に文字列を作成するので、それはCow
という所有のバリアントとして表されるため、結果の値には'static
の有効期間パラメータを使用できます。 orig
に接続することも可能ですが、そうする理由はありません。 Cow
で
割り当てなしのスライスから直接A
の値を作成することも可能である:
fn new(orig: &str) -> A {
A { some_attr: orig.into() }
}
ここA
の寿命パラメータは、入力文字列の寿命に(生涯エリジオン経由)結ばれますスライス。この場合、借用したCow
のバリアントが使用され、割り当ては行われません。
はまた、これらの方法を実行するための書式コードを必要としないので、彼らは、より効率的であるため、String
sまでの文字列スライスを変換するto_owned()
またはinto()
を使用することをお勧めしていることに注意してください。
A
(生涯の'static
)をオンザフライで作成するにはどうすればできますか? 「Cow
の所有変種」とはどういう意味で、なぜ'static
が可能になるのかわかりません。ここで
Cow
の定義です:
pub enum Cow<'a, B> where B: 'a + ToOwned + ?Sized {
Borrowed(&'a B),
Owned(B::Owned),
}
それは複雑に見えますが、それは実際にはシンプルです。 Cow
のインスタンスは、タイプB
への参照を含むか、特性を介してB
から派生することができる所有値のいずれかを含むことがあります。 Cow<str>
文字列スライスまたは所有文字列のいずれかを表すことができる、したがって
pub enum Cow<'a, str> {
Borrowed(&'a str),
Owned(String)
}
- :str
はToOwned
を実装するためOwned
関連するタイプは、それがこのようになり、この列挙はstr
に特化されToOwned<Owned = String>
、として書かString
(に等しいですCow
は実際にクローンオン書き込み機能のメソッドを提供していますが、余分な割り当てを避けるために、借用または所有することができる値を保持するのによく使用されます。Cow<'a, B>
はDeref<Target = B>
を実装するため、Cow<'a, B>
から&B
を取得できます。単純なreboであなたがx
の内容にかかわらずx
がCow<str>
の場合、&*x
は&str
です。当然、Cow
の両方のバリエーションからスライスを得ることができます。
Cow::Owned
には参照が含まれていないことがわかります。String
のみです。したがって、Cow
の値がOwned
バリアントを使用して作成された場合、は任意の生涯を選択できます(生涯パラメータはジェネリック型パラメータとよく似ています;特にそれを選択するのは発信者です)。それに制限はありません。したがって、可能な最大の生涯として'static
を選択するのが理にかなっています。
orig.to_owned
誰でもこの機能を呼び出すの所有権を削除しますか?それは不便なように聞こえる。
to_owned()
方法はToOwned
形質に属する:
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
この特性はString
に等しいOwned
とstr
によって実現されます。 to_owned()
メソッドは、呼び出された値の所有変種を返します。この特定の場合、&str
のうちString
が作成され、文字列スライスの内容を新しい割り当てに効果的にコピーします。したがって、いいえ、to_owned()
は所有権移転を意味するものではなく、「スマート」なクローンを意味するようなものです。
は、私の知る限りは、文字列を伝えることができるようInto<Vec<u8>>
ではなくstr
を実装し、ので、どのように我々は第二の例ではinto()
を呼び出すことができますか?
Into
形質は非常に汎用性があり、標準ライブラリの多くのタイプに実装されています。 Into
は、通常From
の特性によって実装されます:T: From<U>
の場合、U: Into<T>
です。 value
がString
ある場合value
は&str
とCow::Owned(value)
であれば、彼らはただCow::Borrowed(value)
を返す -
impl<'a> From<&'a str> for Cow<'a, str>
impl<'a> From<String> for Cow<'a, str>
これらの実装は非常に単純です:標準ライブラリのFrom
の二つの重要な実装があります。
これは&'a str
とString
はInto<Cow<'a, str>>
を実装することを意味し、そのため彼らはinto()
方法でCow
に変換することができます。これはまさに私の例で起こることです。into()
を使ってString
または&str
をCow<str>
に変換しています。この明示的な変換がなければ、タイプのミスマッチに関するエラーが発生します。
ありがとうございます!しかし、私がここで理解していないことがたくさんあります。あなたはそれをオンザフライで作成しているときに、生涯の '静的'の 'A 'をどのように返すことができますか? 「牛の所有する変種」が何を意味するのか、それがなぜ「静的」を可能にするのかは不明です。私たちはいつでも 'some_attr'をいつでも修正しているわけではありません。それは通常、"書き込み時コピー "のポイントではなく、書き込みを可能にするものですか? 'orig.to_owned'はこの関数を呼び出す人の所有権を削除しますか?それは不便なように聞こえる。 'String'は' Into 'を実装していますが 'str'を実装していないと言うことができるので、第2の例では' into() 'をどのように呼び出すことができますか? –
wrongusername
おっと、それはたくさんの質問です!私は私の答えを更新した、うまくいけば役立つだろう:) –