Cow
- это перечисление, которое расшифровывается как Clone-on-Write
. Его можно использовать в качестве интеллектуального указателя для работы с заимствованными или владеющими значениями. Этот тип может помочь нам избежать ненужного выделения памяти. В этом посте я объясню, как это работает, когда это использовать и зачем это использовать. std::borrow::Cow
Как работают Cow
У нас есть два варианта:
- Заимствование: содержит заимствованную ссылку на данные.
- Владение: содержит владеющего значением.
Когда экземпляр Cow
представлен заимствованным вариантом, это означает, что экземпляр cow
не владеет данными и не может их изменять, он предоставляет представление данных только для чтения.
С другой стороны, если экземпляр Cow
представлен владеющим вариантом, это означает, что экземпляр Cow
владеет данными и может их изменять. Однако данные копируются не сразу, вместо этого они копируются только при попытке внесения изменений.
Использование Cow
Один из наиболее распространенных вариантов использования Cow
- это когда вы работаете со строками. Вот практический пример, иллюстрирующий это.
fn to_uppercase(s: &str) -> Cow<str> {
if s.chars().any(|c| c.is_lowercase()){
Cow::Owned(s.to_uppercase())
}else{
Cow::Borrowed(s)
}
}
Зачем использовать Cow
Cow обеспечивает эффективное и гибкое владение данными без необходимости делать ненужные копии. Это помогает избежать ненужного выделения памяти.
fn to_uppercase_one(s: &str) -> Cow<str> {
if s.chars().any(|c| c.is_lowercase()){
Cow::Owned(s.to_uppercase()) // <-- выделение
}else{
Cow::Borrowed(s)
}
}
fn to_uppercase_two(s: &str) -> String {
if s.chars().any(|c| c.is_lowercase()){
s.to_uppercase() // <-- выделение
}else{
s.to_string() // <-- выделение
}
}
В функции to_uppercase_one
выделение происходит при создании варианта Cow::Owned
. Это создает новую строку, которая является копией исходной строки, преобразованной в верхний регистр, но только в том случае, если исходная строка s
написана в нижнем регистре. Если исходная строка уже написана в верхнем регистре, функция просто заимствует исходную строку без создания копии.
Напротив, функция to_uppercase_two
всегда создает новую строку при каждом ее вызове, поэтому выделение происходит при каждом вызове функции.
Преимущество to_uppercase_one
заключается в том, что он позволяет избежать ненужного выделения и копирования данных, заимствуя исходную строку, когда это возможно. Это может помочь повысить производительность вашей программы Rust, когда вы работаете с большими строками, которые не нужно изменять.
Однако, если вам нужно изменить строку или если исходная строка всегда строчная, использование to_uppercase_two
может быть более подходящим. Эта функция всегда создает собственную копию строки и гарантирует, что результат будет в верхнем регистре.
Вывод
Мы можем сказать, что тип Cow
можно рассматривать как форму необязательного владения. Обеспечивают гибкий способ работы со значениями, которые могут нуждаться в изменении, а могут и не нуждаться, не требуя ненужных копий или выделений, повышая эффективность использования памяти программным обеспечением.