Перейти к содержанию

Что такое Cow в Rust

Posted on:29 марта 2023 г. at 08:23

Example Dynamic OG Image link 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 можно рассматривать как форму необязательного владения. Обеспечивают гибкий способ работы со значениями, которые могут нуждаться в изменении, а могут и не нуждаться, не требуя ненужных копий или выделений, повышая эффективность использования памяти программным обеспечением.