{"componentChunkName":"component---src-templates-post-template-js","path":"/posts/sintaxis-basica-cpp-parte-3","result":{"data":{"markdownRemark":{"id":"fc744c41-f111-5cab-8ce3-38dfd1b1e413","html":"<p>Hola! En esta tercera parte de mi serie sobre sintaxis de C++, hablaré de dos detalles que son cruciales en mi opinión para conseguir programas eficientes que trabajen de la manera más óptima posible con las variables que utilizan en su código: cuándo utilizar la memoria dinámica (<em>heap</em>) y cómo configurar los parámetros de una función para evitar copias innecesarias de recursos y evitar la sobreescritura de argumentos que, en principio, son sólo de entrada.</p>\n<h2 id=\"variables-y-memoria\" style=\"position:relative;\"><a href=\"#variables-y-memoria\" aria-label=\"variables y memoria permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Variables y memoria</h2>\n<p>En esta sección vamos a ver un tema que creo que es importante y es dejado a un lado a mi parecer: ¿en qué parte de la memoria deberíamos guardar las variables con las que trabajamos? ¿En la pila (<em>stack</em>) o en el montículo (<em>heap</em>, memoria dinámica)?</p>\n<p>Tanto <em>stack</em> como <em>heap</em> funcionan de forma diferente al momento de asignar o liberar memoria. En el caso del <em>stack</em>, el sistema operativo asigna una cantidad de memoria a cada proceso para que en él guarde la pila de llamadas (<em>call stack</em>) y las variables locales que cada función pudiera tener. No es una cantidad excesivamente grande (unos cuantos megabytes), pero es suficiente para que un programa pueda alcanzar una buena profundidad de llamadas sin colapsar. El <em>heap</em> es una historia diferente. En este caso podemos pensar literalmente en un montículo lleno de bytes disponibles que se van asignando a los diferentes procesos según lo requieran. Cuando un programa solicita memoria al <em>heap</em> (usando internamente la función <code class=\"language-text\">malloc</code> en sistemas UNIX), este recibe a cambio un puntero ubicando en algún sector de la memoria los bytes que solicitamos. Cuando ya se hizo uso de la memoria, esta se devuelve al montículo (función <code class=\"language-text\">free</code>) para que otros procesos puedan utilizarla. Tanto <em>stack</em> como <em>heap</em> son memoria RAM al fin y al cabo, ¿verdad? Entonces, ¿debiera importarme en cuál de ellas guardo mi información? Absolutamente.</p>\n<p>Aunque en la práctica ambas van a ser igual de rápidas y eficientes, para el programador debe ser importante hacer un buen uso de estas, especialmente considerando que el <em>stack</em> tiene una capacidad limitada (en mi sistema son 8 MiB, para que se hagan una idea) y, al menos en C++, el <em>heap</em> requiere trabajar con punteros, algo que hasta para el programador más avezado podría significar varios dolores de cabeza.</p>\n<p>Una regla que deberían considerar cuando programen es usar punteros la menor cantidad de veces posible, porque aunque sepan al revés y al derecho cómo usarlos, nunca va a faltar la ocasión en que usen <code class=\"language-text\">.</code> en lugar de <code class=\"language-text\">-></code>, terminen con errores de compilación incomprensibles y vean que el programa se la pasa tirando fallos de segmentación porque también les faltó desreferenciar su puntero a alguna estructura y el programa empezó a volverse loco. Lo ideal sería trabajar con punteros sólo cuando tengan que implementar estructuras de datos (como listas, vectores o mapas) y el resto de las ocasiones usar <em>smart pointers</em> (un tipo de objeto que implementa una interfaz más ordenada y menos proclive a errores para trabajar con punteros a memoria). Más adelante podremos ver cómo se utilizan y cuándo.</p>\n<p>Entonces, yendo al grano, ¿cuándo deberíamos usar el heap o el stack? En el caso del <em>stack</em>, podemos utilizarlo con calma cuando trabajemos con arreglos pequeños de tipos pequeños (un arreglo de enteros, de caracteres), estructuras que no tengan un gran tamaño o clases tambien pequeñas:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">int</span> numeros<span class=\"token punctuation\">[</span><span class=\"token number\">50</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">char</span> nombre<span class=\"token punctuation\">[</span><span class=\"token number\">64</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">struct</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> num<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> tipo<span class=\"token punctuation\">[</span><span class=\"token number\">8</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> peque<span class=\"token punctuation\">;</span> <span class=\"token comment\">// Esta notación permite definir una estructura al</span>\n         <span class=\"token comment\">// mismo tiempo que creamos una variable de ese tipo</span>\n\n<span class=\"token keyword\">double</span> x <span class=\"token operator\">=</span> <span class=\"token number\">2.0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Variables comunes y corrientes como esta</span>\n                <span class=\"token comment\">// ya se almacenan en el stack</span>\n\n<span class=\"token comment\">// La clase que creamos anteriormente</span>\nPersona <span class=\"token function\">nic</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Nicholas Cage\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">57</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// INNECESARIO</span>\n<span class=\"token comment\">// Solo ocupa 28 bytes (x86 modernos)</span>\nPersona <span class=\"token operator\">*</span>keanu <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token function\">Persona</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Keanu Reeves\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">56</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Una excepción a esto son tipos como <code class=\"language-text\">std::string</code> o <code class=\"language-text\">std::vector</code>, los cuales solicitan ellos mismos memoria al <em>heap</em> y cuyo tamaño como tal solo corresponde a punteros y números que almacenan información sobre los datos que almacenan:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\">std<span class=\"token double-colon punctuation\">::</span>string saludo <span class=\"token operator\">=</span> <span class=\"token string\">\"¡Hola, mundo!\"</span><span class=\"token punctuation\">;</span>\nstd<span class=\"token double-colon punctuation\">::</span>vector primos<span class=\"token punctuation\">{</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">,</span> <span class=\"token number\">11</span><span class=\"token punctuation\">,</span> <span class=\"token number\">13</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// INNECESARIO</span>\n<span class=\"token comment\">// Tanto ctor como dtor de std::list</span>\n<span class=\"token comment\">// ya contemplan solicitar memoria</span>\n<span class=\"token comment\">// del heap</span>\nstd<span class=\"token double-colon punctuation\">::</span>list<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token operator\">*</span>lista <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> std<span class=\"token double-colon punctuation\">::</span><span class=\"token generic-function\"><span class=\"token function\">list</span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Luego, con respecto al <em>heap</em>, donde brilla es utilizándolo para almacenar grandes cantidades de información, ya sea un gran número de estructuras pequeñas, un número reducido de estructuras enormes o cualquier otra monstruosidad que su programa necesite:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token comment\">// Definitivamente así no es cómo un juego guarda una textura,</span>\n<span class=\"token comment\">// pero en memoria esto va a ocupar ~196 KiB, así que de</span>\n<span class=\"token comment\">// guardarse en el stack lo vamos a llenar bien rápido.</span>\n<span class=\"token comment\">// Por tanto, nos sirve para el ejemplo</span>\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Textura</span> <span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">private</span><span class=\"token operator\">:</span>\n    <span class=\"token keyword\">char</span> r<span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> g<span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> b<span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">public</span><span class=\"token operator\">:</span>\n    <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Esto va a ocupar ~4 MiB de memoria, así que, de guardarse</span>\n<span class=\"token comment\">// en el stack, este no podría aguantar muchas variables</span>\n<span class=\"token comment\">// como esta</span>\nTextura <span class=\"token operator\">*</span>mapa_texs <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> Textura<span class=\"token punctuation\">[</span><span class=\"token number\">64</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">double</span> <span class=\"token operator\">*</span>coefs <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token keyword\">double</span><span class=\"token punctuation\">[</span><span class=\"token number\">1024</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 8 KiB de memoria</span>\n\nTextura <span class=\"token operator\">*</span>jugador <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token function\">Textura</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// ...</span>\n\n<span class=\"token comment\">// No se olviden de liberar la memoria que usen, especialmente</span>\n<span class=\"token comment\">// si el programa va a seguir corriendo después de hacerlo!</span>\n<span class=\"token keyword\">delete</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> mapa_texs<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">delete</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> coefs<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">delete</span> jugador<span class=\"token punctuation\">;</span></code></pre></div>\n<p>Insisto en que manejen bien estas reglas e idealmente investiguen también por cuenta propia cómo funciona lo que explico, porque los malos hábitos nunca mueren y, cuando menos se lo esperen, el proyecto en el que han trabajado por meses empezó a dejar de funcionar porque o llenaron el <em>stack</em> de su programa o el <em>heap</em> ya no tiene espacio para asignar 500 MiB porque ya asignaron chorrocientos elementos de 10 bytes cada uno (creo que esto último no es algo plausible, pero más vale prevenir que lamentar).</p>\n<h2 id=\"uso-adecuado-de-parámetros\" style=\"position:relative;\"><a href=\"#uso-adecuado-de-par%C3%A1metros\" aria-label=\"uso adecuado de parámetros permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Uso adecuado de parámetros</h2>\n<p>Tengo que confesarles algo, buena parte de los ejemplos de código que he entregado no son idóneos realmente. Quiero decir que funcionan como tal, pero he omitido deliberadamente algunos detalles con respecto a algunas variables para motivos de simplicidad. Aquí voy a enmendar mi “error” y les explicaré cómo esperar parámetros adecuadamente en una función y cómo utilizar los <code class=\"language-text\">for</code> basados en rango de forma adecuada desde un punto de vista de memoria, ¡todo en un Solo Cómodo Paquete™! ¡Llame ahora, mientras nuestras operadoras no estén ocupadas!</p>\n<h3 id=\"parámetros-y-argumentos\" style=\"position:relative;\"><a href=\"#par%C3%A1metros-y-argumentos\" aria-label=\"parámetros y argumentos permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Parámetros y argumentos</h3>\n<p>Antes de empezar, les cuento una cosita. No es una regla escrita en piedra, pero por lo general se le denomina <em>parámetros</em> a la lista de variables que una función lleva en su huella (o <em>signature</em>) al momento de definirla, mientras que <em>argumentos</em> se llaman los valores que se le entregan a una función cuando se invoca.</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> a<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Aquí se llaman parámetros</span>\n\n<span class=\"token comment\">// ...</span>\n\n<span class=\"token function\">func</span><span class=\"token punctuation\">(</span><span class=\"token number\">123</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'a'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Y aquí argumentos</span></code></pre></div>\n<p>No es una convención que la totalidad de los programadores siga, pero nunca está de más saberlo.</p>\n<h3 id=\"¿cómo-definimos-los-parámetros-entonces\" style=\"position:relative;\"><a href=\"#%C2%BFc%C3%B3mo-definimos-los-par%C3%A1metros-entonces\" aria-label=\"¿cómo definimos los parámetros entonces permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>¿Cómo definimos los parámetros, entonces?</h3>\n<p>Muy simple. Esta tabla que tienen a continuación explica bien cómo definir los tipos de cada variable según las circunstancias en las que los usen:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 784px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 32.49999999999999%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABYklEQVQY002QWU/CQBSF+8eNTVwoEQ1GfXMBlEWLCBESJVHWKlXWUtqytJ3pQIFSUIwPLiR6CZE4+WZy5uTe83Con78ztF57/Yk5eDG6toYsTGxMRguQsXgtEPMBYoMgvTG1XD46SzHumGs/vu66op3hrb1rhzu6sROlGZZ2sjQTXtm8WGXC2weJNVfE4Y4xuzHq4/PrezaDm0hWPMFMMMJ5Q1lvKONn875Q9vD0zhNMAyeBtCeQ9p1nA5fcsT/lZ3MwRsmKPrSm1mja7Ji1Bq5LhtDAtQYCXRbUdK5UExE4c1NEokJAFIotoFTVKElWrdGbPX5vqaYgGaI8R5CwKJOqqD/wIsQtAR8iqiKq1HX4Uh2th/CAdK2yoCdueYh8rqi5gszxSvK+FL95TKbK3FMzz8t5XgE4vgnkC0qh2KbabV3VMCGm2Z909D7p2V1zDMVCvRoadDRTw8Nl7f/7J137F0lQVS6Nyw0gAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/728daf82ddc007475f71fb3b2990408e/8ac56/cpp-parameters-table.webp 240w,\n/static/728daf82ddc007475f71fb3b2990408e/d3be9/cpp-parameters-table.webp 480w,\n/static/728daf82ddc007475f71fb3b2990408e/2a3bb/cpp-parameters-table.webp 784w\"\n              sizes=\"(max-width: 784px) 100vw, 784px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/728daf82ddc007475f71fb3b2990408e/8ff5a/cpp-parameters-table.png 240w,\n/static/728daf82ddc007475f71fb3b2990408e/e85cb/cpp-parameters-table.png 480w,\n/static/728daf82ddc007475f71fb3b2990408e/4971b/cpp-parameters-table.png 784w\"\n            sizes=\"(max-width: 784px) 100vw, 784px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/728daf82ddc007475f71fb3b2990408e/4971b/cpp-parameters-table.png\"\n            alt=\"Tabla que indica cómo definir los tipos de los parámetros según cómo los usen\"\n            title=\"Tabla que indica cómo definir los tipos de los parámetros según cómo los usen\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n    </span></p>\n<p align=\"center\"><i>Cortesía de <a href=\"https://www.modernescpp.com/index.php/c-core-guidelines-how-to-pass-function-parameters\">Modernes C++</a></i></p>\n<p>De todos modos, explicaré caso a caso cuándo se usa cuál.</p>\n<h4 id=\"parámetros-de-entrada-in\" style=\"position:relative;\"><a href=\"#par%C3%A1metros-de-entrada-in\" aria-label=\"parámetros de entrada in permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Parámetros de entrada (in)</h4>\n<p>Este es el caso más usual que se van a encontrar. Ocurre cuando entregan un valor para que la función lo consuma sin preocuparse de retornarlo a través del mismo:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">imprimir_texto</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string<span class=\"token operator\">&amp;</span> str<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    std<span class=\"token double-colon punctuation\">::</span>cout <span class=\"token operator\">&lt;&lt;</span> str<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">imprimir_texto</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hola\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Acá podemos ver dos cosas: primero, que estamos pasando <code class=\"language-text\">str</code> como una referencia (<code class=\"language-text\">&amp;</code>), lo que quiere decir que no estamos duplicando la variable que entregamos al invocar <code class=\"language-text\">imprimir_texto</code> (estamos trabajando con el mismo literal <code class=\"language-text\">\"Hola\\n\"</code> sin hacer una copia de él). Además, al definirlo como <code class=\"language-text\">const</code>, nos aseguramos de que no vamos a editar innecesariamente a <code class=\"language-text\">str</code>, pues no es el objeto de esta función. Usar <code class=\"language-text\">const</code> o no no afecta su código, sino que simplemente le dice al compilador que esté atento a que la variable no puede reasignarse.</p>\n<p>Este comportamiento de no duplicación no ocurre si omitimos el <code class=\"language-text\">&amp;</code>, lo que puede ser una <strong>muy mala idea</strong> si estamos trabajando con variables muy grandes;</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\">std<span class=\"token double-colon punctuation\">::</span>string texto_muy_largo<span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// ...</span>\n\n<span class=\"token comment\">// Imaginemos que texto_muy_largo contiene un archivo</span>\n<span class=\"token comment\">// de texto de 5 MiB y queremos imprimirlo en pantalla.</span>\n\n<span class=\"token keyword\">void</span> <span class=\"token function\">imprimir_texto_mal</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string str<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    std<span class=\"token double-colon punctuation\">::</span>cout <span class=\"token operator\">&lt;&lt;</span> str<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// En este caso, vamos a trabajar sobre la variable</span>\n<span class=\"token comment\">// misma sin duplicarla, lo que nos ahorra tiempo</span>\n<span class=\"token comment\">// y memoria</span>\n<span class=\"token function\">imprimir_texto</span><span class=\"token punctuation\">(</span>texto_muy_largo<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// En cambio, acá estamos haciendo lo mismo, pero</span>\n<span class=\"token comment\">// de forma más ineficiente, pues estamos duplicando</span>\n<span class=\"token comment\">// el contenido de texto_muy_largo en otra variable</span>\n<span class=\"token comment\">// (el parámetro que recibe la función), lo que</span>\n<span class=\"token comment\">// implica desperdiciar memoria y tiempo copiando</span>\n<span class=\"token comment\">// los contenidos del string</span>\n<span class=\"token function\">imprimir_texto_mal</span><span class=\"token punctuation\">(</span>texto_muy_largo<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Todo esto que expliqué aplica únicamente para tipos que no son baratos de copiar o que simplemente no se pueden copiar (como <code class=\"language-text\">std::unique_ptr</code>, que veremos prontamente). Tipos primitivos como <code class=\"language-text\">int</code> o <code class=\"language-text\">boolean</code> son baratísimos de copiar, por lo que la optimización de usar <code class=\"language-text\">&amp;</code> cuando son parámetros de entrada es innecesaria:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token comment\">// Bien: Barato porque es una referencia a constante</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string<span class=\"token operator\">&amp;</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Mal: Puede ser muy costoso si el string es muy</span>\n<span class=\"token comment\">// grande</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">f2</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>string s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// OK: Imbatible. Podría hasta ser copiado en un</span>\n<span class=\"token comment\">// registro de CPU</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">f3</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Innecesario: Implica una sobrecarga extra para</span>\n<span class=\"token comment\">// convertir la referencia en un valor</span>\n<span class=\"token keyword\">void</span> <span class=\"token function\">f4</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span><span class=\"token operator\">&amp;</span> x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h4 id=\"parámetros-de-salida-out\" style=\"position:relative;\"><a href=\"#par%C3%A1metros-de-salida-out\" aria-label=\"parámetros de salida out permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Parámetros de salida (out)</h4>\n<p>Con parámetro de salida me refiero a aquel que, en vez de ser usado para que la función reciba datos, es usado para retornar información al programador. Esto incluye también al valor de retorno de la función en cierto modo.</p>\n<p>La mayoría de las veces va a ser posible retornar información como parte del retorno de una función sin mayor problema:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token comment\">// Todo esto está bien</span>\n<span class=\"token keyword\">int</span> <span class=\"token function\">f5</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>            <span class=\"token comment\">// Se entrega en el stack</span>\nstd<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">f6</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// Ídem. El contenido del string se</span>\n                        <span class=\"token comment\">// mantiene en el heap.</span></code></pre></div>\n<p>En estos casos corren ciertas optimizaciones que permiten que retornar objetos como un <code class=\"language-text\">std::string</code> no implique un mayor costo para el programa, así que si tienen que retornar uno como en <code class=\"language-text\">f6</code>, pueden hacerlo como si fuera un tipo primitivo más.</p>\n<p>Sin embargo, existe una excepción que, aunque no es algo muy frecuente, vale tener en consideración. Si trabajan con estructuras grandes como esta:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">struct</span> <span class=\"token class-name\">Packet</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">char</span> header<span class=\"token punctuation\">[</span><span class=\"token number\">128</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> payload<span class=\"token punctuation\">[</span><span class=\"token number\">4096</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>pueden encontrarse con problemas si definen una función como <code class=\"language-text\">Packet gen_paquete()</code>, pues retornar más de 4 KiB en el stack puede ser ineficiente, especialmente si se tratara de un arreglo de <code class=\"language-text\">Packet</code>.</p>\n<p>Entonces, ¿qué hacemos para retornar estructuras enormes como esta? Aquí vamos a hacer uso de las referencias no constantes:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">gen_paquete</span><span class=\"token punctuation\">(</span>Packet<span class=\"token operator\">&amp;</span> packet<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Acá, en vez de retornar el paquete de la forma tradicional, lo que hacemos es definir uno vacío y que sea la función la que lo rellene, esto gracias a que estamos trabajando con una copia por referencia. Así, esta función puede ejecutarse de este modo;</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\">Packet p<span class=\"token punctuation\">;</span> <span class=\"token comment\">// Sus arreglos van a estar no inicializados</span>\n\n<span class=\"token function\">gen_paquete</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Acá los inicializamos</span>\n\n<span class=\"token comment\">// Ya en este punto la variable p contiene valores válidos</span></code></pre></div>\n<p>Ya con esto tenemos definidos la mayoría de los casos en que van a encontrarse con parámetros en una función. Existen otros más, los que pueden ver si abren el enlace de donde conseguí la tabla, pero considero que estos son los esenciales y los que importa saber si aún no conocen conceptos más avanzados del lenguaje.</p>\n<h3 id=\"adenda-for-basados-en-rango\" style=\"position:relative;\"><a href=\"#adenda-for-basados-en-rango\" aria-label=\"adenda for basados en rango permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Adenda: <code class=\"language-text\">for</code> basados en rango</h3>\n<p>Considerando lo que hemos visto, si están trabajando con bucles <code class=\"language-text\">for</code> basados en rango, es posible también usar referencias en estas, especialmente si piensan editar los valores que reciben en cada iteración, como pueden ver en este ejemplo:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\">std<span class=\"token double-colon punctuation\">::</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> nums<span class=\"token punctuation\">{</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">&amp;</span> num <span class=\"token operator\">:</span> nums<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    num <span class=\"token operator\">*=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Saliendo del bucle, veremos que nums</span>\n<span class=\"token comment\">// ahora contiene los números {2, 4,</span>\n<span class=\"token comment\">// 6, 8, 10};</span></code></pre></div>\n<p>Con valores chicos como <code class=\"language-text\">int</code>, no debería ser necesario usar referencias si no van a modificarlos, pero, sin embargo, recomiendo encarecidamente usar <code class=\"language-text\">const</code> para evitar posibles <em>bugs</em> si terminan editando el valor involuntariamente:</p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> num <span class=\"token operator\">:</span> nums<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    nun <span class=\"token operator\">*=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// En este caso el compilador</span>\n              <span class=\"token comment\">// saltará con un error</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Con esto terminamos esta entrega de mi ahora ya serie sobre sintaxis básica de C++. Espero verlos en la próxima entrega. ¡Hasta pronto!</p>","fields":{"slug":"/posts/sintaxis-basica-cpp-parte-3","tagSlugs":["/tag/programming/","/tag/c/","/tag/espanol/"]},"frontmatter":{"date":"2021-04-08T14:53:00Z","description":"Uso básico de memoria y buenas prácticas con parámetros.","tags":["Programming","C++","Español"],"title":"[ES] Sintáxis básica de C++ (parte 3)","socialImage":{"publicURL":"/static/f463ff7592afdee2e8660e64fb228e0c/photo.jpg"}}}},"pageContext":{"slug":"/posts/sintaxis-basica-cpp-parte-3"}},"staticQueryHashes":["251939775","3991641674","401334301"]}