---
title: "Cow\u003cT\u003e: Clone on Write em Rust"
url: "https://rustlang.com.br/stdlib/cow/"
markdown_url: "https://rustlang.com.br/stdlib/cow.MD"
description: "Guia completo de Cow\u003cT\u003e em Rust: Clone on Write, Cow\u003cstr\u003e, Cow\u003c[T]\u003e, evitando clonagens desnecessárias e padrões de otimização."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Cow<T>: Clone on Write em Rust

Guia completo de Cow<T> em Rust: Clone on Write, Cow<str>, Cow<[T]>, evitando clonagens desnecessárias e padrões de otimização.


## O que é Cow\<T\>

`Cow<'a, T>` (Clone on Write) é um smart pointer que pode conter um dado **emprestado** (`Borrowed`) ou **possuído** (`Owned`). A ideia central é: manter os dados emprestados sempre que possível e só clonar quando uma modificação for necessária. O nome "Clone on Write" reflete exatamente esse comportamento — a cópia acontece apenas no momento da escrita.

Use `Cow<T>` quando uma função precisa **às vezes** retornar dados emprestados e **às vezes** dados novos. Isso é especialmente comum em funções de processamento de texto (normalização, sanitização, escape) onde a maioria das entradas não precisa de modificação. Em vez de sempre clonar "por precaução", `Cow` adia a cópia até que seja realmente necessária, melhorando a performance.

---

## Criando Cow

```rust
use std::borrow::Cow;

fn main() {
    // Cow<str> — emprestado (referência a &str)
    let emprestado: Cow<str> = Cow::Borrowed("texto literal");

    // Cow<str> — possuído (dona de uma String)
    let possuido: Cow<str> = Cow::Owned(String::from("texto dinâmico"));

    // Usando .into() para conversão ergonômica
    let de_str: Cow<str> = "literal".into();               // Borrowed
    let de_string: Cow<str> = String::from("owned").into(); // Owned

    // Cow<[T]> — com slices
    let slice_emprestado: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]);
    let vec_possuido: Cow<[i32]> = Cow::Owned(vec![4, 5, 6]);

    println!("{emprestado} | {possuido}");
    println!("{de_str} | {de_string}");
    println!("{slice_emprestado:?} | {vec_possuido:?}");

    // Verificando se é emprestado ou possuído
    match &emprestado {
        Cow::Borrowed(_) => println!("Emprestado!"),
        Cow::Owned(_) => println!("Possuído!"),
    }
}
```

---

## Tabela de Métodos Principais

| Método / Operação | Descrição | Exemplo |
|---|---|---|
| `Cow::Borrowed(ref)` | Cria com dado emprestado | `Cow::Borrowed("oi")` |
| `Cow::Owned(val)` | Cria com dado possuído | `Cow::Owned(String::from("oi"))` |
| `to_mut()` | Obtém `&mut T::Owned`, clonando se necessário | `cow.to_mut().push_str("!")` |
| `into_owned()` | Converte para o tipo owned, clonando se emprestado | `cow.into_owned()` → `String` |
| `is_borrowed()` | Verifica se é `Borrowed` (nightly/Rust 1.82+) | `cow.is_borrowed()` |
| `is_owned()` | Verifica se é `Owned` (nightly/Rust 1.82+) | `cow.is_owned()` |
| Deref | Acessa como `&T` | `&*cow` ou `cow.as_ref()` |
| `as_ref()` | Retorna `&str` de `Cow<str>` | `cow.as_ref()` |
| `.into()` | Converte de `&str` ou `String` | `"oi".into()` |

---

## Exemplos Práticos

### 1. Sanitização de Texto (Padrão Clássico)

O caso de uso mais comum de `Cow<str>`: uma função que modifica a string apenas quando necessário.

```rust
use std::borrow::Cow;

fn sanitizar_html(input: &str) -> Cow<str> {
    // Se não contém caracteres especiais, retorna a referência original
    if !input.contains('<') && !input.contains('>') && !input.contains('&') {
        return Cow::Borrowed(input);
    }

    // Só aloca uma nova String quando precisa modificar
    let mut resultado = String::with_capacity(input.len());
    for c in input.chars() {
        match c {
            '<' => resultado.push_str("&lt;"),
            '>' => resultado.push_str("&gt;"),
            '&' => resultado.push_str("&amp;"),
            '"' => resultado.push_str("&quot;"),
            _ => resultado.push(c),
        }
    }
    Cow::Owned(resultado)
}

fn main() {
    let textos = vec![
        "Texto simples sem HTML",
        "Alerta: <script>alert('xss')</script>",
        "Preço: R$ 10 & desconto de 5%",
        "Outro texto normal",
    ];

    for texto in textos {
        let limpo = sanitizar_html(texto);
        let tipo = if matches!(limpo, Cow::Borrowed(_)) {
            "emprestado"
        } else {
            "clonado"
        };
        println!("[{tipo}] {limpo}");
    }
}
```

### 2. Normalização de Caminhos

```rust
use std::borrow::Cow;

fn normalizar_caminho(caminho: &str) -> Cow<str> {
    if caminho.ends_with('/') || caminho.contains("//") {
        let normalizado = caminho
            .trim_end_matches('/')
            .replace("//", "/");
        Cow::Owned(normalizado)
    } else {
        Cow::Borrowed(caminho)
    }
}

fn adicionar_prefixo<'a>(base: &str, caminho: &'a str) -> Cow<'a, str> {
    if caminho.starts_with('/') {
        Cow::Borrowed(caminho)
    } else {
        Cow::Owned(format!("{base}/{caminho}"))
    }
}

fn main() {
    let caminhos = vec![
        "/api/users",
        "/api/users/",
        "/api//users//list",
        "relativo/caminho",
        "/absoluto/caminho",
    ];

    for caminho in &caminhos {
        let normalizado = normalizar_caminho(caminho);
        let com_prefixo = adicionar_prefixo("/v1", caminho);
        println!("{caminho:30} → normalizado: {normalizado:25} | com prefixo: {com_prefixo}");
    }
}
```

### 3. Cow em Structs para Flexibilidade

```rust
use std::borrow::Cow;

#[derive(Debug)]
struct Mensagem<'a> {
    remetente: Cow<'a, str>,
    conteudo: Cow<'a, str>,
    prioridade: u8,
}

impl<'a> Mensagem<'a> {
    /// Cria com dados emprestados (sem alocação)
    fn nova_estatica(remetente: &'a str, conteudo: &'a str) -> Self {
        Mensagem {
            remetente: Cow::Borrowed(remetente),
            conteudo: Cow::Borrowed(conteudo),
            prioridade: 0,
        }
    }

    /// Cria com dados dinâmicos (precisa alocar)
    fn nova_dinamica(remetente: String, conteudo: String) -> Mensagem<'static> {
        Mensagem {
            remetente: Cow::Owned(remetente),
            conteudo: Cow::Owned(conteudo),
            prioridade: 0,
        }
    }

    fn com_prioridade(mut self, p: u8) -> Self {
        self.prioridade = p;
        self
    }

    fn para_owned(self) -> Mensagem<'static> {
        Mensagem {
            remetente: Cow::Owned(self.remetente.into_owned()),
            conteudo: Cow::Owned(self.conteudo.into_owned()),
            prioridade: self.prioridade,
        }
    }
}

fn main() {
    // Sem alocação — usa referências a literais
    let msg1 = Mensagem::nova_estatica("sistema", "Inicialização completa")
        .com_prioridade(1);

    // Com alocação — dados vêm de runtime
    let nome = format!("usuario_{}", 42);
    let texto = format!("Login às {}", "14:30");
    let msg2 = Mensagem::nova_dinamica(nome, texto)
        .com_prioridade(3);

    println!("{msg1:?}");
    println!("{msg2:?}");

    // Converter para owned quando precisar armazenar sem lifetime
    let armazenada: Mensagem<'static> = msg1.para_owned();
    println!("Armazenada: {armazenada:?}");
}
```

### 4. Processamento de Configuração com Valores Padrão

```rust
use std::borrow::Cow;
use std::collections::HashMap;

struct Config {
    valores: HashMap<String, String>,
}

impl Config {
    fn obter<'a>(&'a self, chave: &str, padrao: &'a str) -> Cow<'a, str> {
        match self.valores.get(chave) {
            Some(valor) => Cow::Borrowed(valor.as_str()),
            None => Cow::Borrowed(padrao),
        }
    }

    fn obter_transformado(&self, chave: &str) -> Cow<str> {
        match self.valores.get(chave) {
            Some(valor) if valor == valor.to_uppercase().as_str() => {
                // Já está em maiúsculas, retorna emprestado
                Cow::Borrowed(valor.as_str())
            }
            Some(valor) => {
                // Precisa converter, cria nova String
                Cow::Owned(valor.to_uppercase())
            }
            None => Cow::Borrowed("NAO_DEFINIDO"),
        }
    }
}

fn main() {
    let mut valores = HashMap::new();
    valores.insert("host".to_string(), "localhost".to_string());
    valores.insert("porta".to_string(), "8080".to_string());
    valores.insert("env".to_string(), "PRODUCAO".to_string());

    let config = Config { valores };

    // Valor existente: emprestado
    println!("Host: {}", config.obter("host", "127.0.0.1"));
    // Valor padrão: emprestado (sem alocação!)
    println!("Timeout: {}", config.obter("timeout", "30"));

    // Transformado: depende do caso
    println!("Env: {}", config.obter_transformado("env"));       // Emprestado (já maiúsculo)
    println!("Host: {}", config.obter_transformado("host"));     // Owned (precisou converter)
    println!("DB: {}", config.obter_transformado("db"));         // Emprestado (padrão)
}
```

### 5. Cow<[T]> para Processamento de Slices

```rust
use std::borrow::Cow;

fn remover_zeros(dados: &[i32]) -> Cow<[i32]> {
    if dados.iter().any(|&x| x == 0) {
        // Precisa filtrar: aloca novo Vec
        Cow::Owned(dados.iter().copied().filter(|&x| x != 0).collect())
    } else {
        // Nenhum zero: retorna o slice original
        Cow::Borrowed(dados)
    }
}

fn normalizar_notas(notas: &[f64], maximo: f64) -> Cow<[f64]> {
    let max_atual = notas.iter().copied().fold(f64::NEG_INFINITY, f64::max);

    if (max_atual - maximo).abs() < f64::EPSILON {
        // Já normalizado
        Cow::Borrowed(notas)
    } else {
        // Precisa normalizar
        let fator = maximo / max_atual;
        Cow::Owned(notas.iter().map(|&n| n * fator).collect())
    }
}

fn main() {
    let com_zeros = [1, 0, 3, 0, 5];
    let sem_zeros = [1, 2, 3, 4, 5];

    let r1 = remover_zeros(&com_zeros);
    let r2 = remover_zeros(&sem_zeros);
    println!("Com zeros: {r1:?} (alocado)");
    println!("Sem zeros: {r2:?} (emprestado)");

    let notas = [8.0, 6.0, 10.0, 7.5];
    let ja_normalizado = [80.0, 60.0, 100.0, 75.0];

    let n1 = normalizar_notas(&notas, 100.0);
    let n2 = normalizar_notas(&ja_normalizado, 100.0);
    println!("Normalizado: {n1:.1?}");
    println!("Já ok: {n2:.1?}");
}
```

---

## Dicas de Performance e Armadilhas

1. **Meça antes de otimizar**: `Cow` adiciona complexidade ao código. Use-o quando profiling mostra que clonagens desnecessárias são um gargalo, ou quando a API naturalmente se beneficia (funções de sanitização/normalização).

2. **`to_mut()` clona na primeira chamada**: Após chamar `to_mut()` em um `Cow::Borrowed`, o dado é clonado e passa a ser `Owned`. Chamadas subsequentes a `to_mut()` não clonam novamente.

3. **Lifetimes podem complicar**: `Cow<'a, str>` carrega um lifetime que se propaga pela struct. Se isso for problemático, use `into_owned()` para obter `Cow<'static, str>`.

4. **`Cow` implementa `Deref`**: Você pode passar `&Cow<str>` onde `&str` é esperado, graças à coerção Deref. Isso torna o uso transparente na maioria dos casos.

5. **Tamanho em memória**: `Cow<str>` ocupa 3 palavras de máquina (24 bytes em 64-bit): o discriminante Borrowed/Owned, o ponteiro e o tamanho. É o mesmo que uma `String`.

6. **Alternativas**: Para o caso específico de "emprestado ou owned" em retornos de função, `Cow` é a solução padrão. Não tente reimplementar com `enum { Ref(&str), Own(String) }` — `Cow` já faz isso com ergonomia e integrações com a stdlib.

---

## Veja Também

- [Otimização de Performance em Rust](/artigos/otimizacao-performance/) — técnicas avançadas de otimização
- [String e &str](/stdlib/string/) — `Cow<str>` é a ponte entre `String` e `&str`
- [Slices (&[T])](/stdlib/slice/) — `Cow<[T]>` trabalha com slices
- [Box\<T\>: Alocação no Heap](/stdlib/box-t/) — outro smart pointer para alocação no heap
- [Rc\<T\> e Arc\<T\>](/stdlib/rc-arc/) — quando precisa de ownership compartilhado
- [Cheatsheet Rust](/cheatsheet/) — referência rápida de sintaxe
- [Documentação oficial — std::borrow::Cow](https://doc.rust-lang.org/std/borrow/enum.Cow.html)
