Para ter uma ideia de como é desenvolver em C++, assista à aula do livecoder DenisJose12 sobre estruturas de dados em C++:
O C++ foi inicialmente desenvolvido por Bjarne Stroustrup dos Bell Labs durante a década de 1980 (originalmente com o nome C with Classes, como um adicional à linguagem C) com o objectivo de melhorar a linguagem de programação C ainda que mantendo máxima compatibilidade. Em 1983 o nome da linguagem foi alterado de C with Classes para C++, novas características foram adicionadas, como funções virtuais, sobrecarga de operadores e funções, referências, constantes, gerenciamento manual de memória, melhorias na verificação de tipo de dado e estilo de comentário de código de uma linha (//).
Para aprender mais sobre C++, confira este curso gratuito e com certificado sobre desenvolvimento orientado a objeto em C++ da fundação Bradesco que a CBSI separou.
Após a padronização ISO realizada em 1998 e a posterior revisão realizada em 2003, uma nova versão da especificação da linguagem foi lançada em setembro de 2011, conhecida informalmente como C++11 ou C++0x. Este novo padrão incluirá muitas adições ao núcleo da linguagem (sua implementação principal), e estenderá a biblioteca padrão do C++, incluindo a maior parte da biblioteca do chamado C++ Technical Report 1 — um documento que propõe mudanças ao C++ — com exceção das funções matemáticas específicas.
C++11 introduziu uma sintaxe alternativa para escrever declarações de função. Em vez de colocar o tipo de retorno antes do nome da função (por exemplo, int func () ), a nova sintaxe permite escrever após os parâmetros (por exemplo, auto func () -> int ). Isso leva a duas perguntas: Por que uma sintaxe alternativa foi adicionada? Ela vai substituir a sintaxe original do C++? Para ajudá-lo com essas perguntas, vamos resumir as vantagens e desvantagens desta sintaxe recém-adicionada.
Desde o C++11, temos uma nova maneira de declarar funções. Esta sintaxe alternativa nos permite escrever a seguinte função:
// C or C++98 int f(int x, int y) { // ... }
Como
// C++11 auto f(int x, int y) -> int { // ... }
Basicamente, em vez de escrever o tipo de retorno antes do nome da função, nós colocamos apenas auto e especificamos o tipo de retorno após a lista de parâmetros. Uma vez que o tipo de retorno aparece no final da declaração, diz-se que a função tem um tipo de retorno à direita. Ambas as declarações acima são equivalentes, o que significa que elas significam exatamente o mesmo.
Nota: o uso do auto aqui é apenas parte da sintaxe e não executa dedução de tipo automática neste caso. A dedução automática foi adicionada no C++14, e teria o seguinte efeito se não fornecêssemos o tipo de retorno de retorno:
// C++14 auto f(int x, int y) { // The return type is deduced automatically // based on the function's body. // ... }
Considere a seguinte função, escrita usando a sintaxe alternativa:
// C++11 template<typename Lhs, typename Rhs> auto add(const Lhs& lhs, const Rhs& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }
A função tem dois parâmetros e retorna sua soma. Note que os parâmetros podem ter diferentes tipos, razão pela qual usamos dois parâmetros de modelo diferentes. Contanto que os tipos suportam binário +, eles podem ser usados como argumentos para add(). O especificador decltype nos dá o tipo da expressão lhs + rhs.
Vamos tentar reescrever a função usando a sintaxe padrão:
template<typename Lhs, typename Rhs> decltype(lhs + rhs) add(const Lhs& lhs, const Rhs& rhs) { // error: ^^^ 'lhs' and 'rhs' were not declared in this scope return lhs + rhs; }
Oops! Uma vez que o compilador analisa o código-fonte da esquerda para a direita, o compilador verá lhs e rhs antes de suas definições e rejeita o código. Usando o tipo de retorno à direita, podemos contornar essa limitação.
Nota: a função acima pode ser escrita usando a sintaxe padrão com a ajuda de declval():
Template <typename Lhs, typename Rhs> Declty (std :: declval <Lhs> () + std :: declval <Rhs> ()) add (const Lhs & lhs, const Rhs & rhs) { Return lhs + rhs; }
No entanto, como você pode ver, torna o código menos legível.
Considere a seguinte classe:
class LongClassName { using IntVec = std::vector<int>; IntVec f(); };
Para definir f() usando a sintaxe padrão, temos que duplicar o nome da classe:
LongClassName::IntVec LongClassName::f() { // ... }
O motivo é semelhante ao do exemplo anterior: O compilador analisa o código da esquerda para a direita, por isso, se o compilador viu IntVec, não soube onde procurá-lo porque o contexto (LongClassName) é dado após o tipo de retorno. Com a nova sintaxe, não há necessidade de repetir LongClassName:
auto LongClassName::f() -> IntVec { // ... }
Por último, mas certamente não menos importante, o uso uniforme da nova sintaxe pode levar a um código mais consistente. Por exemplo, quando você define uma expressão lambda, seu tipo de retorno pode ser especificado apenas como o tipo de retorno à direita:
[](int i) -> double { /* ... */ };
Não existe uma sintaxe de tipo de retorno “antiga” para expressões lambda, portanto, não é possível escrever o tipo de retorno no lado esquerdo.
De forma mais geral, como apontado por Herb Sutter, o mundo C ++ está indo para um estilo de declaração da esquerda para a direita em todos os lugares, na forma nome da categoria = tipo e/ou inicializador, em que a categoria pode ser auto ou using. Exemplos:
auto hello = "Hello"s; auto f(double) -> int; using dict = std::map<std::string, std::string>;
Finalmente, uma propriedade um tanto agradável da nova sintaxe é que as declarações de funções agora estão ordenadamente alinhadas por seu nome:
auto vectorize() -> std::vector<int>; auto devour(Value value) -> void; auto get_random_value() -> Value;
No entanto, o alinhamento de nomes de funções parece mais legível apenas quando as funções levam uma linha cada.
No C++14, se você esquecer de especificar o tipo de retorno à direita, um tipo de retorno será deduzido automaticamente. Infelizmente, o tipo deduzido pode não ser o que você quer. Por exemplo, considere a seguinte definição padrão de um operador de atribuição:
auto MyClass::operator=(const MyClass& other) -> MyClass& { value = other.value; return *this; }
Se você omitir o tipo de retorno à direita, o código será compilado, mas ele retornará um valor em vez de uma referência:
auto MyClass::operator=(const MyClass& other) { value = other.value; return *this; // Oops, returns a copy of MyClass! }
Na verdade, a dedução de tipo automático via auto nunca deduz uma referência (se você quiser uma referência, use auto& em vez). Uma omissão descuidada pode assim mudar silenciosamente a semântica do seu código.
Às vezes, a nova sintaxe produz declarações mais longas:
int func(); // vs auto func() -> int;
Independente da experiência, já vimos pessoas atingidas por isso. Considere o seguinte código:
struct A { virtual int foo() const noexcept; }; struct B: A { virtual int foo() const noexcept override
Algumas pessoas esperam que a declaração de B::foo() com a nova sintaxe seja assim:
virtual auto foo() const noexcept override -> int; // error: virtual function cannot have deduced return type
Oops! A forma correta é:
virtual auto foo() const noexcept -> int override;
Ou seja, override tem de ser especificado após o tipo de retorno à direita.
Se você ainda se lembra da lista de prós, você deve se lembrar que a consistência era um dos prós. No entanto, isso só se aplica ao novo código. A maior parte do código existente foi escrito usando a sintaxe padrão. Assim, quando você começar a usar o novo estilo, seu estilo de codificação pode realmente se tornar inconsistente.
Em geral, os programadores não estão familiarizados com a nova sintaxe. Embora isso não seja uma razão contra a nova sintaxe, é algo deve ser lembrado. Para as pessoas que programam em C e C ++ por muito tempo, a nova sintaxe parece estranha. Então, pense duas vezes antes de escrever
auto main() -> int {}
já que isso pode fazer que seus colegas de trabalho queiram bater-lhe com uma vara 🙂
A sintaxe alternativa foi adicionada para auxiliar a escrita de código genérico e para fornecer consistência. No entanto, devido às várias desvantagens listadas acima, a sintaxe original é usada mais amplamente do que a nova sintaxe. Até mesmo as diretrizes do C++ usam a sintaxe original.
We’re thrilled to announce an exciting opportunity for you to win not one but two…
Acquiring practical skills is crucial for career advancement and personal growth. Education Ecosystem stands out…
Artificial Intelligence (AI) has been making significant strides in various industries, and the software development…
Another week to bring you the top yield platforms for three of the most prominent…
If you hold a large volume of LEDU tokens above 1 million units and wish…
It’s another week and like always we have to explore the top yield platforms for…