{"id":1858,"date":"2022-01-24T18:14:09","date_gmt":"2022-01-24T21:14:09","guid":{"rendered":"https:\/\/elemarjr.com\/cppmoderno\/?p=1858"},"modified":"2025-06-18T16:07:31","modified_gmt":"2025-06-18T19:07:31","slug":"use-auto-sempre-que-possivel-capitulo-1-v-1-0","status":"publish","type":"post","link":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/use-auto-sempre-que-possivel-capitulo-1-v-1-0\/","title":{"rendered":"Use &#8216;auto&#8217; sempre que poss\u00edvel \/ Cap\u00edtulo 1 v 1.0"},"content":{"rendered":"<p>Este cap\u00edtulo mostra um recurso pequeno do C++ moderno. Algo simples, familiar para programadores de outras linguagens, mas que pode ter impacto gigante, devidamente utilizado, em bases de c\u00f3digo legadas de dif\u00edcil legibilidade. Trata-se da palavra-chave <code>auto<\/code> &#8211; algo semelhante a <code>var<\/code> para programadores C# e Java, mas bem mais poderoso em C++.<\/p>\n<p><code>auto<\/code> \u00e9 t\u00e3o bem-aceito, simples e impactante\u00a0 que <a href=\"https:\/\/pt.wikipedia.org\/wiki\/Herb_Sutter\">Herb Sutter<\/a>, um dos \u00edcones de C++, que trabalha na Microsoft, evangeliza seu uso de maneira intensiva.<\/p>\n<h2>Os compiladores C++ est\u00e3o ficando mais amig\u00e1veis<\/h2>\n<p><strong>Historicamente, o principal compromisso dos compiladores C++ \u00e9 gerar o melhor execut\u00e1vel poss\u00edvel a partir do c\u00f3digo-fonte fornecido pelo desenvolvedor.<\/strong> Os compiladores n\u00e3o criticam voc\u00ea, tampouco julgam suas motiva\u00e7\u00f5es. Eles simplesmente assumem que voc\u00ea sabe (ou, pelo menos, deveria saber) o que est\u00e1 fazendo!<\/p>\nNo passado, compiladores C++ eram famosos por n\u00e3o ajudarem muito na detec\u00e7\u00e3o de erros no c\u00f3digo. Ali\u00e1s, eram comuns as cr\u00edticas as &#8220;centenas&#8221; (exagerando, mas nem tanto) de mensagens de erro e alertas para um &#8220;ponto-e-v\u00edrgula&#8221; fora de lugar. Essa condi\u00e7\u00e3o, entretanto, faz parte do passado, pelo menos para c\u00f3digo escrito em um estilo moderno.\n<hr \/>\n<p><strong>Um bom exemplo de como compiladores C++ modernos, e a pr\u00f3pria linguagem, tem adaptado sua filosofia \u00e9 o suporte amplo a palavra-chave <code>auto<\/code> &#8211; uma abstra\u00e7\u00e3o, com custo zero, para que seja identificado, a partir do c\u00f3digo, o tipo que o desenvolvedor intenciona usar.\u00a0<\/strong><\/p>\n<h2><code>auto<\/code> no C++11<\/h2>\n<p>A partir do C++11, <code>auto<\/code> passou a ser uma alternativa na declara\u00e7\u00e3o de vari\u00e1veis locais.<\/p>\n<pre>auto a = 42;        \/\/ 'a' type is integer.\r\nauto b = 27.5;      \/\/ 'b' type is double.\r\nauto c = \"Elemar\";  \/\/ 'c' type is char const *\r\n\r\nauto d = {4, 5, 6}; \/\/ 'd' type is std::initializer_list&lt;int&gt;\r\nauto f = [](unsigned char c) { return std::toupper(c); };\r\n<\/pre>\n<p>Usando <code>auto<\/code> o programador transfere para o compilador a responsabilidade de inferir o tipo apropriado para as vari\u00e1veis (da mesma forma como <code>var<\/code> ajuda em linguagens como Java e C#). Isso reduz bastante a verbosidade dos c\u00f3digos, sem custos. Na pr\u00e1tica, essa vis\u00e3o mais abstrata permite a evolu\u00e7\u00e3o natural do c\u00f3digo, diminuindo necessidade de revis\u00f5es.<\/p>\n<hr \/>\n<p>Eventualmente, a escolha padr\u00e3o de tipos do compilador poder\u00e1 n\u00e3o ser a desejada. No exemplo acima, poderia ser desej\u00e1vel que\u00a0 a vari\u00e1vel <code>c<\/code> fosse declarada como <code>std::string<\/code>, no lugar de <code>char const *<\/code>. Ou ainda, a vari\u00e1vel <code>d<\/code> ficaria melhor como <code>std::vector&lt;int&gt;<\/code> no lugar de <code>std::initializer_list&lt;int&gt;<\/code>. Nestes casos, uma alternativa \u00e9 usar a sintaxe de constru\u00e7\u00e3o <strong><code>auto n = type-name { expression }<\/code><\/strong> , como segue:<\/p>\n<pre>auto c = std::string {\"Elemar\"}; \r\nauto d = std::vector&lt;int&gt; {4, 5, 6}; \r\n<\/pre>\n<p>Simples, mas efetivo.<\/p>\n<h4><em>Trailing Return Types<\/em><\/h4>\n<p>At\u00e9 aqui, <code>auto<\/code> em C++ parece, muito, com <code>var<\/code> de Java e C#. Mas, como j\u00e1 foi dito, <code>auto<\/code> vai muito al\u00e9m.<\/p>\n<p>A partir do C++11, h\u00e1 um novo formato para declara\u00e7\u00e3o de fun\u00e7\u00f5es: usando\u00a0<em>trailing return types. <\/em>Trata-se de\u00a0uma sintaxe alternativa de declara\u00e7\u00e3o de fun\u00e7\u00f5es que permite que o tipo de retorno seja especificado depois da lista de par\u00e2metros.<\/p>\n<pre>\/\/ C++98\r\nint foo(int a, int b) {\r\n  \/\/ ..\r\n}\r\n\r\n\/\/ C++11\r\nauto foo(int a, int b) -&gt; int {\r\n  \/\/ ..\r\n}\r\n<\/pre>\n<p>Na nova forma de declara\u00e7\u00e3o, o tipo de retorno \u00e9 especificado ap\u00f3s a lista de par\u00e2metros, e n\u00e3o antes. A palavra-chave <code>auto<\/code>, aqui, n\u00e3o \u00e9 respons\u00e1vel por qualquer tipo de infer\u00eancia, apenas indicativo de que o tipo de retorno ser\u00e1 especificado depois.<\/p>\n<p>A principal motiva\u00e7\u00e3o para a nova nota\u00e7\u00e3o \u00e9 a possibilidade de ampliar o poder de declara\u00e7\u00e3o de <em>templates<\/em>.<\/p>\n<pre>C++98\r\ntemplate &lt;typename L, typename R&gt;\r\ndecltype (std::declval&lt;L&gt;() + std::declval&lt;R&gt;()) foo(L&amp; a, R&amp; b) {\r\n  \/\/ ..\r\n}\r\n\r\n\/\/ C++11\r\ntemplate &lt;typename L, typename R&gt;\r\nauto foo(L&amp; a, R&amp; b) -&gt; decltype(a + b) {\r\n  \/\/ ..\r\n}\r\n<\/pre>\n<p>A segunda sintaxe, usando a ideia <em>trailing return type<\/em>,\u00a0\u00e9 poss\u00edvel, sabendo que o compilador processa c\u00f3digo da esquerda para a direita, porque a lista de par\u00e2metros j\u00e1 foi declarada e <code>a<\/code> e <code>b<\/code> j\u00e1 foram descobertos.<\/p>\n<h2><code>auto<\/code> no C++14<\/h2>\n<p>A partir do C++14, <code>auto<\/code> pode ser usado, tamb\u00e9m, na declara\u00e7\u00e3o de par\u00e2metros em fun\u00e7\u00f5es <em>lambda<\/em>.<\/p>\n<pre>auto add = [](auto const a, auto const b) { return a + b; };<\/pre>\n<p>Al\u00e9m disso, a linguagem agora tamb\u00e9m suporta a utiliza\u00e7\u00e3o de auto em fun\u00e7\u00f5es que n\u00e3o utilizem <em>trailing return types<\/em>.<\/p>\n<pre>auto foo(int a, int b) {\r\n  \/\/ ..\r\n}\r\n<\/pre>\n<p>Simplesmente tente criar um c\u00f3digo como o que segue em C# ou Java.<\/p>\n<pre>auto add(auto a, auto b) {\r\n    return a + b;\r\n}\r\n\r\nint main() {\r\n\r\n    std::cout\r\n      &lt;&lt; add(2, 3) &lt;&lt; std::endl\r\n      &lt;&lt; add(std::string{\"Elemar\"}, \"Jr\");\r\n}\r\n<\/pre>\n<h2>Benef\u00edcios de usar <code>auto<\/code> sempre que poss\u00edvel<\/h2>\n<p>A utiliza\u00e7\u00e3o de <code>auto<\/code> impede que programadores C++ deixem vari\u00e1veis sem inicializa\u00e7\u00e3o &#8211; um engano comum entre programadores, mesmo experientes. Al\u00e9m disso, garante que um tipo mais apropriado (correto?!) seja associado a uma vari\u00e1vel, impedindo a ocorr\u00eancia de convers\u00f5es implicitas ou perda de precis\u00e3o.<\/p>\n<pre>auto vec = std::vector {1, 2, 3};\r\nint  count1 = vec.size();  \/\/ possible conversion loss\r\nauto count2 = vec.size(); \/\/ 'count2' type is size_t;\r\n<\/pre>\n<p>Na pr\u00e1tica, <code>auto<\/code> permite a escrita de menos c\u00f3digo (ainda menos do que <code>var<\/code> autoriza em C# e Java), reduzindo preocupa\u00e7\u00f5es com tipos que n\u00e3o s\u00e3o realmente importantes (como <em>iterators<\/em>, por exemplo).<\/p>\n<pre>std::map&lt;int, std::string&gt; m;\r\n\r\n\/\/ C++98\r\nfor (std::map&lt;int, std::string&gt;::const_iterator it = m.cbegin();\r\n  it != m.cend(); \r\n  ++it)\r\n{\r\n  \/\/  \r\n}\r\n\r\n\/\/ C++11\r\nfor (auto it = m.cbegin(); it != m.cend(); ++it)\r\n{ \r\n  \/\/..\r\n}\r\n<\/pre>\n<h2>Mas nem tudo s\u00e3o flores&#8230;<\/h2>\n<p>A utiliza\u00e7\u00e3o de <code>auto<\/code> em C++, embora mais poderosa que <code>var<\/code> de C# e Java, \u00e9 mais perigosa tamb\u00e9m.<\/p>\n<p><code>auto<\/code> detecta apenas o tipo a partir de uma express\u00e3o, ignorando se o valor \u00e9 uma constante (<code>const<\/code>) ou vol\u00e1til (<code>volatile<\/code>). Tamb\u00e9m ignora indicadores de refer\u00eancia ou apontamento.<\/p>\n<pre>#include &lt;iostream&gt;\r\n\r\nclass Envelope {\r\n  int _data;\r\npublic:\r\n  Envelope(int const data = 0) : _data { data }\r\n  {}\r\n\r\n  int&amp; get() { return _data; };\r\n};\r\n\r\nint main() {\r\n  Envelope instance(42);\r\n\r\n  auto  x = instance.get();\r\n  auto&amp; y = instance.get();\r\n  auto  z = x;\r\n  auto&amp; w = y;\r\n\r\n  x = 10;\r\n  y = 11;\r\n  z = 12;\r\n  w = 13;\r\n\r\n  std::cout\r\n      &lt;&lt; instance.get() &lt;&lt; \" \"\r\n      &lt;&lt; x &lt;&lt; \" \" &lt;&lt; y &lt;&lt; \" \" &lt;&lt; z &lt;&lt; \" \" &lt;&lt; w;\r\n\r\n  \/\/ 13 10 13 12 13\r\n}\r\n<\/pre>\n<p>No c\u00f3digo acima, por exemplo, <code>x<\/code> e <code>z<\/code> s\u00e3o do tipo <code>int<\/code> e n\u00e3o <code>int&amp;<\/code>.<\/p>\n<p>Uma alternativa, mais segura, quando o objetivo de uma express\u00e3o \u00e9 criar vari\u00e1veis com tipos id\u00eanticos &#8211; considerando const\u00e2ncia, volatilidade, apontamento e refer\u00eancias &#8211; de outras vari\u00e1veis \u00e9 o uso de <code>decltype<\/code>.<\/p>\n<pre>int main(){\r\n  Envelope instance(42);\r\n\r\n  auto&amp; x = instance.get();\r\n  decltype(x) y = instance.get();\r\n  decltype(x) z = x;\r\n  decltype(x) w = y;\r\n\r\n  x = 10;\r\n  y = 11;\r\n  z = 12;\r\n  w = 13;\r\n\r\n  std::cout\r\n    &lt;&lt; instance.get() &lt;&lt; \" \"\r\n    &lt;&lt; x &lt;&lt; \" \" &lt;&lt; y &lt;&lt; \" \" &lt;&lt; z &lt;&lt; \" \" &lt;&lt; w;\r\n\r\n  \/\/ 13 13 13 13 13\r\n}\r\n<\/pre>\n<p>Novamente, nada facilmente encontrado em outras linguagens!<\/p>\n<h2>Para pensar!<\/h2>\n<p>C++ moderno inclui uma s\u00e9rie de facilitadores e est\u00e1 mais expressiva &#8211; <code>auto<\/code> \u00e9 um bom exemplo! Entretanto, a linguagem n\u00e3o perde sua caracter\u00edstica de maximizar poder, eventualmente, sacrificando &#8220;seguran\u00e7a&#8221;.<\/p>\n<p>Recursos isolados de C++ n\u00e3o previnem enganos. Entretanto, a combina\u00e7\u00e3o de recursos modernos torna a ocorr\u00eancia deles cada vez mais rara.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Este cap\u00edtulo mostra um recurso pequeno do C++ moderno. Algo simples, familiar para programadores de outras linguagens, mas que pode ter impacto gigante, devidamente utilizado, em bases de c\u00f3digo legadas de dif\u00edcil legibilidade. Trata-se da palavra-chave auto &#8211; algo semelhante a var para programadores C# e Java, mas bem mais poderoso em C++. auto \u00e9 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":1916,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"hashtags":[],"tipo":[38],"url":[37],"apendices":[],"capitulos":[14],"class_list":["post-1858","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tipo-capitulo","url-permanente","capitulos-capitulo-1"],"_links":{"self":[{"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/posts\/1858","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/comments?post=1858"}],"version-history":[{"count":56,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/posts\/1858\/revisions"}],"predecessor-version":[{"id":1956,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/posts\/1858\/revisions\/1956"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/media\/1916"}],"wp:attachment":[{"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/media?parent=1858"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/categories?post=1858"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/tags?post=1858"},{"taxonomy":"hashtags","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/hashtags?post=1858"},{"taxonomy":"tipo","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/tipo?post=1858"},{"taxonomy":"url","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/url?post=1858"},{"taxonomy":"apendices","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/apendices?post=1858"},{"taxonomy":"capitulos","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/cpp-moderno\/wp-json\/wp\/v2\/capitulos?post=1858"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}