<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Allan Batista]]></title><description><![CDATA[Allan Batista]]></description><link>https://allanbatista.com.br</link><generator>RSS for Node</generator><lastBuildDate>Mon, 27 Apr 2026 07:54:46 GMT</lastBuildDate><atom:link href="https://allanbatista.com.br/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Ownership e Borrowing em Rust]]></title><description><![CDATA[O conceito de Ownership e Borrowing é, sem dúvidas, o principal desafio para nós desenvolvedores quando começamos a aprender Rust. Acredito que essa dificuldade existe porque as principais linguagens do mercado não possuem nada parecido com isso. Mas...]]></description><link>https://allanbatista.com.br/ownership-e-borrowing-em-rust</link><guid isPermaLink="true">https://allanbatista.com.br/ownership-e-borrowing-em-rust</guid><category><![CDATA[Rust]]></category><category><![CDATA[rust lang]]></category><category><![CDATA[ownership]]></category><category><![CDATA[borrowing]]></category><category><![CDATA[rust-ownership]]></category><category><![CDATA[rust borrowing]]></category><dc:creator><![CDATA[Allan Batista]]></dc:creator><pubDate>Tue, 18 Jun 2024 16:00:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718666373945/58855e3c-127a-499b-b1ec-5e92f1258126.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>O conceito de Ownership e Borrowing é, sem dúvidas, o principal desafio para nós desenvolvedores quando começamos a aprender Rust. Acredito que essa dificuldade existe porque as principais linguagens do mercado não possuem nada parecido com isso. Mas, uma vez que dominamos esse conceito, todo o conhecimento adicional da linguagem não será muito diferente do que já vimos em outras linguagens.</p>
<h1 id="heading-ownership">Ownership</h1>
<p>O <strong>Ownership em RUST</strong> visa garantir um software mais seguro em termos de gerenciamento de memória. Para que isso seja possível, o RUST implementa diversas regras que são avaliadas durante a compilação do programa. Dessa forma, todo programa que compila, está livre desses problemas.</p>
<h2 id="heading-gerenciamento-de-memoria">Gerenciamento de Memória</h2>
<p>Diferente de linguagens que possuem <a target="_blank" href="https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29">Garbage Collector</a> (ex.: C# e Java), Rust é mais comparável com C e C++, onde precisamos controlar a alocação e liberação da memória <strong>HEAP</strong>.</p>
<p>A principal vantagem de o desenvolvedor ter controle da memória é que o software usa e libera apenas a quantidade necessária de memória para funcionar. Isso ocorre sem um processo (GC) que interrompa a execução do programa de tempos em tempos para recuperar a memória ocupada por objetos que não estão mais sendo usados.</p>
<p>A principal desvantagem é que o controle e gerenciamento ficam totalmente nas mãos do desenvolvedor, o que acaba gerando erros com muito mais frequência do que gostaríamos.</p>
<p><strong>Principais erros de gerenciamento de memória:</strong></p>
<ol>
<li><p><strong>Double Free</strong>: Ocorre quando a memória é liberada mais de uma vez</p>
</li>
<li><p><strong>Memory Leak</strong>: Ocorre quando a memória alocada nunca é liberada</p>
</li>
<li><p><strong>Dangling Pointer</strong>: Ocorre quando um ponteiro mantém a referência da memória mesmo após a sua liberação</p>
</li>
<li><p><strong>Buffer Overflow</strong>: Ocorre quando continuamos escrevendo na memória, mesmo após atingirmos o limite da memória alocada</p>
</li>
</ol>
<h3 id="heading-stack-e-heap">Stack e Heap</h3>
<p>Assim como todas as principais linguagens de mercado, Rust também possui alocação de memória em STACK e HEAP para o seu funcionamento.</p>
<h4 id="heading-stack"><strong>Stack</strong></h4>
<p>A stack é uma área de memória usada para armazenar variáveis locais e informações de controle de funções, organizada em uma estrutura LIFO (Last In, First Out), essa estratégia permite uma alocação muito rápida da memória necessária.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>O tamanho da variável Stack é conhecida em tempo de compilação e as variáveis são automaticamente desalocadas quando o saem do escopo.</strong></div>
</div>

<h4 id="heading-heap"><strong>Heap</strong></h4>
<p>A heap é uma área de memória usada para alocações dinâmicas, que podem variar em tamanho e vida útil. Em Rust, a alocação na heap é gerenciada pelo sistema através de smart pointers, como `Box`, `Rc`, e `Arc`.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>O tamanho da variável Stack é conhecida em tempo de execução.</strong></div>
</div>

<h2 id="heading-entendendo-o-ownership"><strong>Entendendo o Ownership</strong></h2>
<p>Para entender o ownership, precisamos lembrar que só pode existir um "dono" de uma variável em qualquer momento.</p>
<p>Existem três cenários quando usamos uma variável:</p>
<ol>
<li><p>Ocorre uma cópia implícita da variável na stack.</p>
</li>
<li><p>A variável é emprestada para outro escopo (borrowing).</p>
</li>
<li><p>A variável é passada por referência (como se fosse um ponteiro).</p>
</li>
</ol>
<h3 id="heading-copia-implicita">Cópia Implícita</h3>
<p>No exemplo abaixo, podemos ver que ao definir uma variável qualquer, o dono do valor é transferido diretamente para o "nome" da variável e na sequência transferimos (cópia) o seu valor para a função <code>println</code>.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
   <span class="hljs-comment">// idade é o owner do valor 32</span>
   <span class="hljs-keyword">let</span> idade = <span class="hljs-number">32</span>;

   <span class="hljs-comment">// o valor de idade é copiado e</span>
   <span class="hljs-comment">// passado como valor para a função println</span>
   <span class="hljs-built_in">println!</span>(<span class="hljs-string">"idade={}"</span>, idade);
}
</code></pre>
<p>Esse comportamento só é possível, pois estamos utilizando um tipo de dado que implementa o <code>Trait</code> de <code>Copy</code> (todos os tipos de dados primitivos da linguagem possuem <code>Copy</code>).</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Em Rust, um <code>Trait</code> define um comportamento que pode ser utilizado por diferentes objetos. Ele é similar a interfaces em outras linguagens e permite especificar métodos que devem ser implementados por tipos que desejem aderir ao <code>Trait</code>. Traits facilitam a abstração e polimorfismo.</div>
</div>

<p>Fazendo uma analogia do código com a memória stack. Ocorre uma cópia do valor da variável.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718462341001/1d96292f-48c5-499a-9f68-faba2be72f9d.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Dessa forma, a variável idade mantem o ownership do valor 32, mesmo quando é utilizada mais de uma vez. Isso porque o ownership nunca é transferido e o valor sempre é copiado quando necessário. Esse comportamento é adequado porque a variável é pequena e possui um tamanho pré-definido.</div>
</div>

<h3 id="heading-borrowing-emprestando-valores">Borrowing - Emprestando valores</h3>
<p>O Borrowing garante que existirá apenas um dono por vez de um valor, porém podendo existir mais de uma referência para a mesma. Dessa forma, uma vez que a varável dono chegue ao final do escopo onde está declarada, sua memória será automaticamente liberada.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-comment">// Stack</span>
    <span class="hljs-keyword">let</span> pessoa: Pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
    <span class="hljs-comment">// estamos transferindo o ownership nesse momento e faz com</span>
    <span class="hljs-comment">// que a variável pessoa não possa mais ser utilizada. (borrow)</span>
    <span class="hljs-keyword">let</span> pessoa_copia: Pessoa = pessoa;

    <span class="hljs-comment">// mostra o endereço das variáveis</span>
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço da variável pessoa é {:p}"</span>, &amp;pessoa); 
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço da variável pessoa_copia é {:p}"</span>, &amp;pessoa_copia);

    <span class="hljs-comment">// mostra o valor das variáveis</span>
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"valor da variável pessoa é {:?}"</span>, pessoa);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"valor da variável pessoa_copia é {:?}"</span>, pessoa_copia);
}
</code></pre>
<p><strong>Erro de compilação:</strong></p>
<pre><code class="lang-rust">error[E0382]: borrow of moved value: `pessoa`
  --&gt; src/main.rs:<span class="hljs-number">12</span>:<span class="hljs-number">52</span>
   |
<span class="hljs-number">8</span>  |     <span class="hljs-keyword">let</span> pessoa: Pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
   |         ------ <span class="hljs-keyword">move</span> occurs because `pessoa` has <span class="hljs-class"><span class="hljs-keyword">type</span> `<span class="hljs-title">Pessoa</span></span>`, which does not implement the `<span class="hljs-built_in">Copy</span>` <span class="hljs-class"><span class="hljs-keyword">trait</span>
11 |     <span class="hljs-title">let</span></span> pessoa_copia: Pessoa = pessoa;
   |                                ------ value moved here
...
<span class="hljs-number">14</span> |     <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço da variável pessoa é {:p}"</span>, &amp;pessoa); 
   |                                                    ^^^^^^^ value borrowed here after <span class="hljs-keyword">move</span>
</code></pre>
<p>No exemplo acima, vemos que é gerado um erro durante a compilação alegando que a variável pessoa está emprestada (borrowing). Esse exemplo se diferencia do caso do exemplo anterior porque <code>Struct</code> por padrão não implementa a <code>Trait</code> de <code>Copy</code> e pessoa está sendo emprestada para <code>pessoa_copia</code> e não pode mais ser utilizada.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Vale ressaltar que neste caso, ambas as variáveis se encontram na Stack.</div>
</div>

<p>Uma vez que a Struct implementa Copy, ela pode ser passada da mesma forma que o exemplo de <strong>Cópia Implícita</strong>.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug, Copy, Clone)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">A trait Copy depende da trait Clone, por isso ambas são definidas em derive.</div>
</div>

<p><strong>Saída da Execução:</strong></p>
<pre><code class="lang-rust">endereço da variável pessoa é <span class="hljs-number">0x7fff7a0bb9b0</span>
endereço da variável pessoa_copia é <span class="hljs-number">0x7fff7a0bb9b4</span>
valor da variável pessoa é Pessoa { idade: <span class="hljs-number">32</span> }
valor da variável pessoa_copia é Pessoa { idade: <span class="hljs-number">32</span> }
</code></pre>
<p>Vale observar que ambas as variáveis possuem o mesmo valor em endereços de memória diferentes. Literalmente ocorreu uma cópia do valor.</p>
<h3 id="heading-passando-valores-por-referencia">Passando valores por referência</h3>
<p>Ficar copiando os valores de um lado para o outro não é nada elegante. Principalmente quando precisamos passar valores relativamente grandes e copiá-los sem necessidade.</p>
<p>Para isso, podemos utilizar a passagem de valores por referência e por sorte, esse comportamento é supersimples.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-comment">// Stack</span>
    <span class="hljs-keyword">let</span> pessoa: Pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
    <span class="hljs-comment">// Pessoa -&gt; &amp;Pessoa / pessoa -&gt; &amp;pessoa</span>
    <span class="hljs-keyword">let</span> pessoa_copia: &amp;Pessoa = &amp;pessoa;

    <span class="hljs-comment">// mostra o endereço das variáveis</span>
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço da variável pessoa é {:p}"</span>, &amp;pessoa);
    <span class="hljs-comment">// removemos o &amp; de pessoa_copia, pois queremos apontar para o</span>
    <span class="hljs-comment">// endereço de memória do destino da referência e não para o </span>
    <span class="hljs-comment">// endereço da referência</span>
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço da variável pessoa_copia é {:p}"</span>, pessoa_copia);

    <span class="hljs-comment">// mostra o valor das variáveis</span>
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"valor da variável pessoa é {:?}"</span>, pessoa);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"valor da variável pessoa_copia é {:?}"</span>, pessoa_copia);
}
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Uma outra opção menos elegante seria Clonar o valor da variável. (pessoal.clone()) Isso funcionaria, mas estariamos gastando o dobro de memória sem necessidade.</div>
</div>

<p><strong>Saída da Execução:</strong></p>
<pre><code class="lang-rust">endereço da variável pessoa é <span class="hljs-number">0x7ffeede39484</span>
endereço da variável pessoa_copia é <span class="hljs-number">0x7ffeede39484</span>
valor da variável pessoa é Pessoa { idade: <span class="hljs-number">32</span> }
valor da variável pessoa_copia é Pessoa { idade: <span class="hljs-number">32</span> }
</code></pre>
<p>A imagem abaixo exemplifica o que acontece na Stack.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718465037884/8c98db8b-a1ed-4edf-a696-4800b5ee471f.png" alt class="image--center mx-auto" /></p>
<p>Neste caso temos alguns comportamentos importantes:</p>
<ol>
<li><p>Pessoa não implementa mais Copy</p>
</li>
<li><p>O tipo da variável <code>pessoa_copia</code> deixa de ser <code>Pessoa</code> e passa a ser <code>&amp;Pessoa</code> (podemos ler como "Referência de Pessoa")</p>
</li>
<li><p>A atribuição passa ser a referência da variável <code>&amp;pessoa</code> (é retornado a referência do endereço de memória de <code>pessoa</code>)</p>
</li>
<li><p><code>pessoa_copia</code> não aponta mais para um novo valor, aponta para o mesmo valor da variável pessoa.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Referências podem ser utilizadas quantas vezes forem necessárias, pois ela diz para o compilador que está apenas lendo o valor da uma variável, mas nunca assumindo a responsabilidade por ela.</div>
</div>

<p><strong>Transferência de Ownership</strong></p>
<p>O que acontece quando retornamos à referência de uma variável em um escopo que já foi finalizado?</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cria_pessoa</span></span>() -&gt; &amp;Pessoa {
    <span class="hljs-keyword">let</span> pessoa: Pessoa = Pessoa { idade: <span class="hljs-number">32</span> };

    &amp;pessoa
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> pessoa = cria_pessoa();
}
</code></pre>
<p><strong>Saída da Compilação</strong></p>
<pre><code class="lang-rust">error[E0106]: missing lifetime specifier
 --&gt; src/main.rs:<span class="hljs-number">6</span>:<span class="hljs-number">21</span>
  |
<span class="hljs-number">6</span> | <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cria_pessoa</span></span>() -&gt; &amp;Pessoa {
  |                     ^ expected named lifetime parameter
  |
  = help: this function<span class="hljs-symbol">'s</span> <span class="hljs-keyword">return</span> <span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-title">contains</span></span> a borrowed value, but there is no value <span class="hljs-keyword">for</span> it to be borrowed from
help: consider using the `<span class="hljs-symbol">'static</span>` lifetime, but this is uncommon unless you<span class="hljs-symbol">'re</span> returning a borrowed value from a `<span class="hljs-keyword">const</span>` or a `<span class="hljs-keyword">static</span>`
  |
<span class="hljs-number">6</span> | <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cria_pessoa</span></span>() -&gt; &amp;<span class="hljs-symbol">'static</span> Pessoa {
  |                      +++++++
help: instead, you are more likely to want to <span class="hljs-keyword">return</span> an owned value
  |
<span class="hljs-number">6</span> - <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cria_pessoa</span></span>() -&gt; &amp;Pessoa {
<span class="hljs-number">6</span> + <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cria_pessoa</span></span>() -&gt; Pessoa {
  |

error[E0515]: cannot <span class="hljs-keyword">return</span> reference to local variable `pessoa`
 --&gt; src/main.rs:<span class="hljs-number">9</span>:<span class="hljs-number">5</span>
  |
<span class="hljs-number">9</span> |     &amp;pessoa
  |     ^^^^^^^ returns a reference to data owned by the current function
</code></pre>
<p>É claro que temos um erro. Isso porque a variável que definimos só existe dentro do escopo da função e é imediatamente removida assim que o escopo é finalizado.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Existe um segundo conceito chamado Lifetime, mas não é o momento para essa discussão.</div>
</div>

<p>Para resolver esse caso, bastaria retornar <code>Pessoa</code>, fazendo assim a transferência de Ownership para o escopo "pai".</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cria_pessoa</span></span>() -&gt; Pessoa {
    <span class="hljs-keyword">let</span> pessoa: Pessoa = Pessoa { idade: <span class="hljs-number">32</span> };

    pessoa
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-comment">// agora o ownership é da variável pessoa no escopo atual</span>
    <span class="hljs-keyword">let</span> pessoa = cria_pessoa();

    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"pessoa={:?}"</span>, pessoa);
}
</code></pre>
<p><strong>Saída da Execução</strong></p>
<pre><code class="lang-rust">pessoa=Pessoa { idade: <span class="hljs-number">32</span> }
</code></pre>
<h2 id="heading-alocacao-de-espacos-de-memoria-na-heap">Alocação de espaços de memória na Heap</h2>
<p>Até o momento, vimos a criação, cópia e referência de variáveis definidas apenas na Stack, porém quando precisamos criar variáveis que o tamanho é desconhecido em tempo de compilação, precisamos recorrer a Heap.</p>
<pre><code class="lang-rust"><span class="hljs-keyword">use</span> std::rc::Rc;

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> x: Rc&lt;<span class="hljs-built_in">i32</span>&gt; = Rc::new(<span class="hljs-number">32</span>);
    <span class="hljs-keyword">let</span> y: Rc&lt;<span class="hljs-built_in">i32</span>&gt; = x.clone();

    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"mostra o endereço das variáveis"</span>);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço do valor da variável x é {:p}"</span>, &amp;x);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço do valor da variável y é {:p}"</span>, &amp;y);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">""</span>);

    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"mostra o endereço na heap"</span>);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço do valor da variável x é {:p}"</span>, x);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"endereço do valor da variável y é {:p}"</span>, y);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">""</span>);

    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"mostra o valor das variáveis"</span>);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"valor da variável x é {}"</span>, x);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"valor da variável y é {}"</span>, y);
}
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Rc é um tipo de Smart Pointer que aloca o valor da variável diretamente na Heap e quando a variável é clonada ela não copia o valor, ela incrementa o seu contador sem a necessidade de copiar o valor do conteúdo na Heap.</div>
</div>

<p><strong>Saída da Execução</strong></p>
<pre><code class="lang-rust">mostra o endereço das variáveis
endereço <span class="hljs-keyword">do</span> valor da variável x é <span class="hljs-number">0x7ffd60241688</span>
endereço <span class="hljs-keyword">do</span> valor da variável y é <span class="hljs-number">0x7ffd60241690</span>

mostra o endereço na heap
endereço <span class="hljs-keyword">do</span> valor da variável x é <span class="hljs-number">0x555b86246bb0</span>
endereço <span class="hljs-keyword">do</span> valor da variável y é <span class="hljs-number">0x555b86246bb0</span>

mostra o valor das variáveis
valor da variável x é <span class="hljs-number">32</span>
valor da variável y é <span class="hljs-number">32</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718473129897/bab749af-9532-417c-a42d-c411781dd9a2.png" alt class="image--center mx-auto" /></p>
<p>Nesse exemplo, usamos um tipo de dado i32, mas poderíamos ter utilizado qualquer tipo de dado. A única informação que precisaria ser copiada para a transferência seria um Rc de tamanho fixo que estaria na Stack enquanto o valor continuaria na Heap.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">O Rc ficará responsável por eliminar qualquer referência da heap ao final da última ocorrência da referência.</div>
</div>

<h3 id="heading-mutabilidade-das-variaveis">Mutabilidade das variáveis</h3>
<p>Até o momento, vimos o comportamento apenas de variáveis imutáveis, de tal forma que só precisamos garantir que quando formos usar uma variável, ou fazemos uma cópia ou passamos por referência.</p>
<p>Por padrão, toda variável definida é imutável.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> idade = <span class="hljs-number">32</span>;

    <span class="hljs-comment">// gera um erro. por padrão toda variável é imutável por padrão</span>
    idade = <span class="hljs-number">33</span>;
}
</code></pre>
<p><strong>Saída da compilação</strong></p>
<pre><code class="lang-rust">error[E0384]: cannot assign twice to immutable variable `idade`
 --&gt; src/main.rs:<span class="hljs-number">5</span>:<span class="hljs-number">5</span>
  |
<span class="hljs-number">2</span> |     <span class="hljs-keyword">let</span> idade = <span class="hljs-number">32</span>;
  |         -----
  |         |
  |         first assignment to `idade`
  |         help: consider making this binding mutable: `<span class="hljs-keyword">mut</span> idade`
...
<span class="hljs-number">5</span> |     idade = <span class="hljs-number">33</span>;
  |     ^^^^^^^^^^ cannot assign twice to immutable variable
</code></pre>
<p>Formas de trabalhar com variáveis mutáveis:</p>
<ol>
<li><p>Mutabilidade de variáveis sem referência</p>
</li>
<li><p>Transferência de Ownership de uma variável para outro escopo</p>
</li>
<li><p>Mutabilidade de variáveis com referência</p>
</li>
</ol>
<p><strong>Existe apenas uma referência para a variável</strong></p>
<p>Então, para podermos atualizar o valor de uma variável, basta que seja definido a variável como mutável.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> idade = <span class="hljs-number">32</span>; <span class="hljs-comment">// basta definir como mut</span>

    idade = <span class="hljs-number">33</span>;
    idade = <span class="hljs-number">34</span>;
    idade = <span class="hljs-number">35</span>;
}
</code></pre>
<p>Porém, o que acontece se tentarmos utilizar os valores e depois tentar fazer essa atribuição quando usamos variáveis que implementam Copy.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> idade = <span class="hljs-number">32</span>;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"idade={}"</span>, idade);

    idade = <span class="hljs-number">33</span>;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"idade={}"</span>, idade);
}
</code></pre>
<p>Mesmo que tenhamos utilizado e feito uma nova atribuição, a variável continua sendo utilizável porque neste cenário, sempre é feito a cópia implícita dos valores.</p>
<p><strong>Transferência de Ownership de uma variável para outro escopo</strong></p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">incrementa_idade</span></span>(p: Pessoa) {
    p.idade += <span class="hljs-number">1</span>;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"2 pessoa={:?}"</span>, pessoa);
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"1 pessoa={:?}"</span>, pessoa);

    incrementa_idade(pessoa);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"3 pessoa={:?}"</span>, pessoa);
}
</code></pre>
<p><strong>Saída da Compilação</strong></p>
<pre><code class="lang-rust">error[E0594]: cannot assign to `p.idade`, <span class="hljs-keyword">as</span> `p` is not declared <span class="hljs-keyword">as</span> mutable
 --&gt; src/main.rs:<span class="hljs-number">7</span>:<span class="hljs-number">5</span>
  |
<span class="hljs-number">7</span> |     p.idade += <span class="hljs-number">1</span>;
  |     ^^^^^^^^^^^^ cannot assign
  |
help: consider changing this to be mutable
  |
<span class="hljs-number">6</span> | <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">incrementa_idade</span></span>(<span class="hljs-keyword">mut</span> p: Pessoa) {
  |                     +++

error[E0382]: borrow of moved value: `pessoa`
  --&gt; src/main.rs:<span class="hljs-number">16</span>:<span class="hljs-number">31</span>
   |
<span class="hljs-number">12</span> |     <span class="hljs-keyword">let</span> pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
   |         ------ <span class="hljs-keyword">move</span> occurs because `pessoa` has <span class="hljs-class"><span class="hljs-keyword">type</span> `<span class="hljs-title">Pessoa</span></span>`, which does not implement the `<span class="hljs-built_in">Copy</span>` <span class="hljs-class"><span class="hljs-keyword">trait</span>
...
15 |     <span class="hljs-title">incrementa_idade</span></span>(pessoa);
   |                      ------ value moved here
<span class="hljs-number">16</span> |     <span class="hljs-built_in">println!</span>(<span class="hljs-string">"3 pessoa={:?}"</span>, pessoa);
   |                               ^^^^^^ value borrowed here after <span class="hljs-keyword">move</span>
   |
note: consider changing this parameter <span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-title">in</span></span> function `incrementa_idade` to borrow instead <span class="hljs-keyword">if</span> owning the value isn<span class="hljs-symbol">'t</span> necessary
  --&gt; src/main.rs:<span class="hljs-number">6</span>:<span class="hljs-number">24</span>
   |
<span class="hljs-number">6</span>  | <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">incrementa_idade</span></span>(p: Pessoa) {
   |    ----------------    ^^^^^^ this parameter takes ownership of the value
   |    |
   |    <span class="hljs-keyword">in</span> this function
</code></pre>
<p>No momento em que chamamos a função <code>incrementa_idade</code>, transferimos o ownership da variável para a função e além de passarmos o ownership, também passamos uma variável imutável.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">incrementa_idade</span></span>(p: &amp;<span class="hljs-keyword">mut</span> Pessoa) {
    p.idade += <span class="hljs-number">1</span>;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"2 pessoa={:?}"</span>, p);
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"1 pessoa={:?}"</span>, pessoa);

    incrementa_idade(&amp;<span class="hljs-keyword">mut</span> pessoa);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"3 pessoa={:?}"</span>, pessoa);
}
</code></pre>
<p><strong>Saída da Execução</strong></p>
<pre><code class="lang-rust"><span class="hljs-number">1</span> pessoa=Pessoa { idade: <span class="hljs-number">32</span> }
<span class="hljs-number">2</span> pessoa=Pessoa { idade: <span class="hljs-number">33</span> }
<span class="hljs-number">3</span> pessoa=Pessoa { idade: <span class="hljs-number">33</span> }
</code></pre>
<p>Podemos notar que tivemos que definir <code>mut</code> em todas as declarações e passagem de parâmetros. Isso no primeiro momento parece bem chato, porém, sabemos exatamente onde e quando uma variável receberá mutação.</p>
<p><strong>Mutabilidade de variáveis com referência</strong></p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">incrementa_idade</span></span>(p: &amp;<span class="hljs-keyword">mut</span> Pessoa) {
    p.idade += <span class="hljs-number">1</span>;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"2 pessoa={:?}"</span>, p);
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"1 pessoa={:?}"</span>, pessoa);

    <span class="hljs-keyword">let</span> p2 = &amp;pessoa;

    incrementa_idade(&amp;<span class="hljs-keyword">mut</span> pessoa);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"3 pessoa={:?}"</span>, pessoa);

    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"4 p2={:?}"</span>, p2);
}
</code></pre>
<p><strong>Saída da Compilação</strong></p>
<pre><code class="lang-rust">error[E0502]: cannot borrow `pessoa` <span class="hljs-keyword">as</span> mutable because it is also borrowed <span class="hljs-keyword">as</span> immutable
  --&gt; src/main.rs:<span class="hljs-number">17</span>:<span class="hljs-number">22</span>
   |
<span class="hljs-number">15</span> |     <span class="hljs-keyword">let</span> p2 = &amp;pessoa;
   |              ------- immutable borrow occurs here
<span class="hljs-number">16</span> |
<span class="hljs-number">17</span> |     incrementa_idade(&amp;<span class="hljs-keyword">mut</span> pessoa);
   |                      ^^^^^^^^^^^ mutable borrow occurs here
...
<span class="hljs-number">20</span> |     <span class="hljs-built_in">println!</span>(<span class="hljs-string">"4 p2={:?}"</span>, p2);
   |                           -- immutable borrow later used here
</code></pre>
<p>Nesse caso, vemos que não é permitido existir uma referência mutável e imutável ao mesmo tempo.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Pessoa</span></span> {
    idade: <span class="hljs-built_in">i32</span>
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">incrementa_idade</span></span>(p: &amp;<span class="hljs-keyword">mut</span> Pessoa) {
    p.idade += <span class="hljs-number">1</span>;
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"2 pessoa={:?}"</span>, p);
}

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> pessoa = Pessoa { idade: <span class="hljs-number">32</span> };
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"1 pessoa={:?}"</span>, pessoa);

    incrementa_idade(&amp;<span class="hljs-keyword">mut</span> pessoa);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"3 pessoa={:?}"</span>, pessoa);

    <span class="hljs-keyword">let</span> p2 = &amp;pessoa;

    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"4 p2={:?}"</span>, p2);
}
</code></pre>
<p>Uma vez que alteramos a ordem das referências mutáveis e imutáveis, fazendo com que a referência mutável seja finalizada antes da criação da referência. Dessa forma, não há problemas e podemos seguir sem problemas.</p>
<h2 id="heading-referencias">Referências:</h2>
<ol>
<li><p><a target="_blank" href="https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html">https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/lQ7XF-6HYGc?si=mdl5uRtfL_l0KQhp">https://youtu.be/lQ7XF-6HYGc?si=mdl5uRtfL_l0KQhp</a></p>
</li>
<li><p><a target="_blank" href="https://nnethercote.github.io/perf-book/heap-allocations.html">https://nnethercote.github.io/perf-book/heap-allocations.html</a></p>
</li>
</ol>
]]></content:encoded></item></channel></rss>