ded3 0 Denunciar post Postado Janeiro 23, 2012 Eu comecei a estudar C++ recentemente e encontrei algumas dúvidas com relação ao que seria melhor usar em um código... Duvida 1: Qual é a diferença entre usar: int FuncA() { ... } ou usar: int FuncA(void) { ... } Duvida 2: Existe alguma diferença no peso do #define e no uso de const? Alguma diferença na aplicação de ambas? Duvida 3: É melhor usar: using namespace std; cout << "oi" << endl; ou é melhor usar: std::cout << "oi" << std::endl; (foi só um exemplo de uso de std, mas a duvida mesmo é no geral, pra todas as funções que usem ele) Duvida 4: Gostaria de saber se exite alguma diferença no processamento de strings nesses 2 casos: cout << string1 << string2 << endl; E: cout << string1 + string2 << endl; Duvida 5: Gostaria de saber qual desses 2 códigos seria mais leve: if(x != 100){ if(x < 10) func; else if(x < 30) func2; else if(x < 80) func3; else func4; } Ou: if(x == 100); else if(x < 10) func; else if(x < 30) func2; else if(x < 80) func3; else func4; Duvida 6: Existe alguma diferença no peso da operação, quando os valores são mais altos? por exemplo: x = x*900/1000; E: x = x*9/10; Duvida 7: O uso de conversões pesa mais do que operações matemáticas a mais? por exemplo: x = (int)(y/2. + z/5.); Ou: x = (5*y + 2*z)/10; Qual desses dois seria melhor? Duvida 8: Existe alguma diferença no peso de uma multiplicação e de uma divisão no caso de double/floats? por exemplo: x = (y/2. + z/5.); Ou x = 0.5*y + 0.2*z; Duvida 9: Qual tipo de variável é mais vantajoso usar? Por exemplo, temos um valor que não ultrapassa o valor máximo de um int16, mas eu estou usando um sistema de 32 bits. Uma vez eu li que se um processador de 32 bits roda um int16, ele faz todo o processo em int32 para depois converter em int16, tornando a execução mais lenta, isso realmente ocorre? nesse caso, seria mais vantajoso usar o int16 por usar menos memória, ou o int32 por ser executado mais rapidamente pelo processador? Desculpe o tanto de perguntas, mas são dúvidas que eu tenho já há algum tempo x.x Compartilhar este post Link para o post Compartilhar em outros sites
Renato Utsch 24 Denunciar post Postado Janeiro 23, 2012 Olá! Dúvida 1: Em C++ não há diferença, há só em C. Mas, por boa prática, é melhor por void. Dúvida 2: A diferença nos 2 é que o #define vai ser substituído por um valor literal, enquanto o const vai ser uma variável que não é permitido modificar. Já ouvi falar que alguns compiladores, quando você habilita otimização, substituiem o valor no const por literais, mas sem otimizações não dá, pois até a intenção do const é você ver a constante pelo nome dela quando estiver debuggando, e não pelo valor, como no define. Dúvida 3: Com certeza é melhor usar especificando o namespace. Não é por acaso que o namespace existe, ele é para evitar conflitos. Então, sempre use. Mas lembre-se que funções macro não tem namespace, então talvez seja melhor você dar #undef na função de macro para ter acesso à função inline que é equivalente: #include <cstdio> #undef getchar // Dará acesso à função inline std::getchar() Pode ser chato ficar colocando std::, mas você se acostuma rápido, e é a boa prática. Dúvida 4: Bom, não tenho certeza, mas vamos analizar. utilizar o operador + vai causar um tanto de operações para juntar as 2 strings, enquanto o outro só manda para a stdout duas vezes. EU acho que o primeiro modo é mais rápido, por não ter que gerar operações de soma de string, o que normalmente é pesado, imagino que mais do que chamar a stream duas vezes. Dúvida 5: Não tenho certeza qual é mais leve, mas acho que a segunda opção talvez nem compile em alguns compiladores com warnings no máximo (tipo GCC com -Wall -Wextra -Werror), porque você está fazendo um null statement. A boa prática é a primeira opção. Dúvida 6: Bom, não sei. A intuição nos leva a dizer que quanto maior o número mais demorada a operação. E isso é parcialmente verdade quanto a diferenças entre números de 8bits, 16bits, 32bits e 64bits. Tenho certeza que leva mais clock cycles do processador para fazer uma divisão de 32bits do que de 8bits, por exemplo. Mas aí eu acho que a diferença é entre esses tamanhos. Dúvida 7: Não tenho certeza. Eu sei que dentro das instruções de assembly a divisão e a multiplicação estão dentre as instruções mais pesadas, talvez mais que as de conversão. Principalmente as de conversão de signed. Unsigned são bem mais rápidos, pois as operações são mais rápidas e na conversão não é necessário preocupar com o sign bit, sendo também mais rápido. Talvez converter de float para int seja mais lento, não tenho noção de como funciona as instruções para números decimais (digo, com casas decimais) no assembly, só inteiros =/ Você realmente tem que fazer um benchmark, mas não acho que esse tipo de coisa vá desacelerar sua aplicação, essa diferença é praticamente insignificante, a não ser que aconteça MUITAS vezes. Dúvida 8: Cara, também não faço ideia nessa. Mas, com toda a certeza, não haverá diferença em um bom compilador (vulgo GCC, Visual Studio, etc)... Dúvida 9: Essa dúvida também me assolava há algum tempo. Comecei a aprender assembly e vi que isso tudo é mito Os processadores, pelo o menos o x86 e x86_64 trabalham nativamente em qualquer tamanho de dado. É até mais rápido trabalhar com inteiros de 8bits se comparado a inteiros de 32bits ou 64bits (para x86_64), bem mais rápido. Se uso um int16, o processador trabalha com int16, e não com int32. Isso eu tenho certeza para x86 e x86_64, então é sempre vantajoso usar o tamanho que você precisa. A não ser que o compilador seja uma bos** para fazer esse tipo de conversão. Em assembly, não existe isso. Então, é sempre vantajoso usar o tamanho que você precisa, por ser mais rápido e usar menos memória. O problema maior nesse tipo de coisa é caso você for converter os tamanhos, digamos de um int8 para colocar em um int16, isso é lento, não utilizar eles só. Outra dica para você: muita gente fala para evitar unsigned, eu lhe direi o contrário. Toda vez que não for usar números negativos, use unsigned (não importa o tamanho). Operações com unsigned são bem mais rápidas, e conversões também. É uma dica de otimização que os compiladores não podem fazer. Eles esperam que, já que declarou como signed, que vá usar a parte negativa. SEMPRE use unsigned caso não for usar números negativos. Aí é só tormar cuidado com signed/unsigned mismatch, mas com prática você vai ver que não é difícil. Abraços :D Compartilhar este post Link para o post Compartilhar em outros sites
HwapX 20 Denunciar post Postado Janeiro 23, 2012 Renato Utsch Duvida 1 Eu discordo, se você consultar o faq lite que esta off pra mim, vai ver que isso é um padrão do C e não do C++ e que é considerado uma aberração neste. Duvida 2 é isso entre outras coisas. Duvida 3 Eu não vejo necessidade do uso para um programa pequeno, que segue os padrões e que não esta tendo nenhum conflito. Duvida 4 De acordo. Duvida 5 Sem duvida o segundo é horrivel neste ponto é melhor presar o mais legivel, para uma facil manutenção, são casos raros em que se tem que preocupar a tão baixo nivel com o desempenho do programa, lembrando que quanto mais otimização mais dificil é sua leitura/manutenção. Duvida 6 Isso é relativo, eu pessoalmente penso que seria levado mais em conta o tamanho de onde estes dados estão armazenados do que o seu valor mesmo, ainda assim isso é algo desconsideravel para um programa "normal" pois nem por isso um programa rodando em uma maquina de 64 bits é mais lento, se compilado para a arquitetura 64 bits pode até ser mais rapido. Duvida 7 Existem as conversões implicitas tambem, então ao meu ver como bom metodo de programação é melhor fazer o cast dos valores, alem de como eu disse antes acho irrelevante ninguem é tão mal programador a ponto de precisar deste tipo de preucupação, são casos mais isolados em que isso é necessario. Duvida 8 As instruções seriam semelhantes, alem de que quando os valores são conhecidos o compilador geralmente faz o pré calculo. Duvida 9 Para um grande software sem necessidade de nada especial o melhor seria utilizar o tamanho padrão dos tipos, facilitaria a manutenção no caso de futuramente vir a trabalhar com numeros maiores, sem ter que alterar o codigo em massa é horrivel isso, agora se você tiver uma necessidade especial como pouca memoria ai sim você deve se preucupar em usar tipos com tamanhos menores. Signed - Unsigned Agora quanto a variaveis com sinal ou sem bom mesmo que não se vá utilizar valores negativos é melhor utilizar o sinal (a não ser que você vá utilizar um numero grande que possa ser armazenado eliminando o sinal) pois assim facilita a manutenção do codigo, evita erros de comparação quando por algum motivo o valor vier a ter um valor negativo então facilitaria o debug, seria mais facil para outra pessoa fazer manutenção no codigo pois não precisaria necessariamente conhecer tudo. Então resumidamente sempre preze a legibilidade do codigo, siga os padrões(salvo casos estritamente especiais) evita problemas facilita a vida dos outros e a sua. Muitas desta duvidas são respondidas olhando a documentação, outras são futeis para mim. Bom de qualquer forma essa a minha opnião sugiro ao autor do topico que LEIA a documentação e ESTUDE ai você vai tirar as suas proprias conclusões sem precisar de opnião de terceiros. Compartilhar este post Link para o post Compartilhar em outros sites
Renato Utsch 24 Denunciar post Postado Janeiro 23, 2012 Hacker_wap Dúvida 1 Bom saber ^^ Dúvida 9 Mas e se você tiver certeza que não vai utilizar mais? É essa a situação. Não importa o que você diga de que talvez um dia eu possa pensar em que talvez eu possa pensar em talvez utilizar mais valores (sim, isso mesmo), eu NÃO vou utilizar números maiores. Então, o mais vantajoso é utilizar o tipo menor, não? Signed / Unsigned Então, é justamente sobre isso que eu falo: programadores tem medo de usar unsigned. É boa prática usar unsigned em todos os valores que não utilizam números negativos, a máquina funciona assim e nós deveríamos fazer isso também. Se você está fazendo comparações com signed e unsigned você já está errado de começo, não é assim que as coisas funcionam, então eu mantenho minha ideia de que você deve utilizar unsigned's. Lembre-se que se você está utilizando unsigned é porque você tem CERTEZA que não vai utilizar números negativos, por isso tire da cabeça que há a menor possibilidade de o número ficar negativo, se há o cara que fez o código está errado. Abraços :D Compartilhar este post Link para o post Compartilhar em outros sites
HwapX 20 Denunciar post Postado Janeiro 24, 2012 O Faq esta online agora. Duvida 1 http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.4 Duvida 2 Sobre Macros http://renangreinert.blogspot.com/2011/08/maldicao-das-macros.html Tipos http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.5 Unsigned / Signed Tem também o problema com a comparação de unsigned e signed. http://renangreinert.blogspot.com/2011/10/signedunsigned-mismatch.html Eu tive um problema com unsigned que gostaria de dizer mais infelizmente não me lembro qual foi, só que tive um bom trabalho até descobrir a causa. http://kaba.hilvi.org/pastel/techniques_unsigned.htm http://critical.eschertech.com/2010/04/07/danger-unsigned-types-used-here/ Só posso repetir uma coisa utilize com SABEDORIA. Cast Mais um detalhe sobre o cast ele esta utilizando o cast do C e não do C++ (static_cast, const_cast, dynamic_cast, reinterpret_cast). http://www.pontov.com.br/site/cpp/46-conceitos-basicos/81-c-type-casting-2o-parte Todos estes sites tem coisas muito interessantes sobre o assunto vale a pena visitar e todos eles e não se ater somente aos posts dos links. Apesar de ser contra eu eu tenho vícios com tipos e unsigned também. É aquele ditado faça o que eu digo mais não faça o que eu faço. Depois destes links acho que não existe mais motivo para discutir, ainda que não pratiquemos isso é um fato que não pode ser negado é um vicio ruim, não devemos passar e nem encorajar abitos ruins. Att, tudo de bom :). Compartilhar este post Link para o post Compartilhar em outros sites
Renato Utsch 24 Denunciar post Postado Janeiro 24, 2012 Pois é, eu concordo em tudo com você menos com o problema de signed / unsigned. Esse tipo de signed/unsigned mismatch é algo que não deve acontecer, se o cara fez isso ele está errado, repito a dizer. Simplesmente, nós estamos programando em C++, é uma linguagem mais low-level, nós temos que ter noção de que não podemos ter toda a segurança de uma linguagem high-level. Nós estamos programando em C++ porque queremos desempenho. Utilizar unsigned E o tamanho certo em programas realmente grandes (vamos dizer, um jogo a nível da ubisoft, crytek, etc ou um sistema operacional) faz uma enorme diferença. O certo é programar assim, não importa o que qualquer um que quer a segurança de uma lang. high level em C++ diga. Você está programando em C++, então VOCÊ tem que ter cuidado com algumas coisas. Então eu continuo a dizer, utilize os tamanhos certos e unsigned onde possível e você estará certo. Abraços :D Compartilhar este post Link para o post Compartilhar em outros sites
ded3 0 Denunciar post Postado Janeiro 24, 2012 Desculpa pela demora para responder, mas fiquei sem pc e estou no celular, entao nao da para abrir os links e nem testar os codigos... Ate segunda feira acho que ja poderei testar devidamente. Obrigado pelas respostas e dicas extras, eu realmente nao tinha encontrado essas respostas em alguma doc/apostila online. E tipo, eu sei que mais otimizado fica mais dificil de ler, mas eh mais para saber como seria o jeito mais otimizado. Compartilhar este post Link para o post Compartilhar em outros sites
ded3 0 Denunciar post Postado Janeiro 27, 2012 Duvida 1: Bom, já que não usar void não trará nenhum prejuizo ao programa, dúvida resolvida. Duvida 2: Então, no caso de números é melhor usar const mesmo, ok. Isso vale para strings também? Se não, o #define serviria só para compilação condicional, certo? No caso de criar macros, seria melhor usar inline? Duvida 3: Resolvido, vou começar a me acostumar a usar o "std::" então... @renato Não entendi muito bem essa parte do #undef, mas depois eu faço alguns testes e dou uma pesquisada para entender melhor. Obrigado pela dica. Duvida 4: Hmm, vou usar o << mesmo então, obrigado. Duvida 5: O segundo modo eu já vi em uns 3~4 lugares (talves não em c++, mas funciona também)... Desconsiderando qual é o modo mais legivel e considerando apenas que os 2 funcionam, o primeiro seria mais rápido? Não sei como funciona o else, mas será que ele não precisaria de um certo "cache" pra funcionar, o que tornaria ele mais pesado? Duvida 6: Acho que vou usar números menores mesmo... Se tornar mais rápido, ótimo, se não, pelo menos diminui o risco de ultrapassar o valor maximo e dar problema na conta. Duvida 7: Bom, acho que nenhuma resposta foi muito concreta nesse caso de conversão de float para int x.x @hacker_wap Mas vou dar uma olhada no cast do c++, obrigado pela dica Duvida 8: Nenhuma resposta definitiva também. @renato Você citou que multiplicação e divisão são umas das instruções mais pesadas... Existe algum doc ou algo nos headers que indique isso? Talves possa indicar também qual das duas é a mais pesada. Duvida 9: Então, eu não tinha visto nada sobre isso nas apostilas e tal, mas estava pesquisando uma outra coisa no google e acabou aparecendo um blog com dicas de programação e lá dizia que o uso de int16 por exemplo em um SO de 32bits seria mais lento do que o uso de um int32... Mas então, se o que pesa mais é a conversão durante o script, o melhor seria usar o menor tamanho que trabalhe corretamente com os valores e em casos que em uma outra parte do script tenha que haver uma conversão, é melhor já usar direto o valor maior? Me surgiu uma dúvida aqui com relação ao endl... Pelo que eu vi, ele é mais pesado que o \n, então o mais indicado em casos de texto como: frase1 frase2 frase3 seria usar algo como: std::cout << "frase1\n frase2\n frase3" << std::endl; Por conta do \n ser mais leve? (ou seja, sempre que possivel, deve usar \n a não ser que seja a última frase antes de entrar em outra função). Enfim, obrigado pelas dicas extras sobre cast e unsigned/signed, isso vai ajudar bastante já que comecei a estudar c++ há pouco tempo e ainda não conheço muito da linguagem. @edit Desculpa pelo double, não tinha visto que o ultimo post era meu x.x Compartilhar este post Link para o post Compartilhar em outros sites
Renato Utsch 24 Denunciar post Postado Janeiro 30, 2012 Dúvida 2: Vale para strings também. Inline é sempre melhor. Dúvida 3: Tipo, a STD da C diz que é obrigatório (na maioria das vezes, tem umas poucas excessões) que quando a implementação (no caso, o compilador) disponibiliza uma função macro, ela precisa também fornecer uma função real, com protótipo e talz. Para acessar ela é só digitar: #undef nome_da_função Aí o macro vai ser substituído por uma função real, que fica no namespace. Em C++, normalmente os protótipos são inline. Um exemplo bem clássico é o getchar(): inline int getchar() { return getc(stdin); } #define getchar() getc(stdin) Dúvida 5: Não faço ideia, pesquise na source de um compilador (gcc recomendado) para descobrir ^^ Dúvida 7: Conversão de float para int apenas vai truncar o resultado, fazendo de conta que a parte decimal nunca existiu. Agora, essa truncagem deve ser lenta, pois o modo como o float é armazenado na memória é COMPLETAMENTE diferente do modo com o int é, então uma grande conversão seria necessária. Dúvida 8: Apenas leia algum livro sobre assembly, talvez até a referência de assembly x86 da intel fale isso. Agora, entre as 2, não sei qual a mais pesada não. Dúvida 9: O que quer que esse blog falou sobre in16 ser mais lento em SO's de 32bits ele tava erradíssimo. Ele ouviu de uma fonte errada e colocou algo errado no blog dele, sem fundamentos. Seria melhor usar o menor tamanho para trabalhar corretamente, se precisar de um tamanho maior, apenas faça a conversão. Nâo é algo que vá desacelerar mais do que alguns clocks do processador não... O std::endl é mais pesado mesmo, pois ele faz o mesmo que as seguntes funções da C: printf("\n"); fflush(stdout); Além de inserir um caractere de nova linha, ele limpa o buffer de saída, mostrando o resultado na hora mesmo. Então é sempre bom você usar ele, mas pode usar o '\n' se quiser. Abraços :D Compartilhar este post Link para o post Compartilhar em outros sites
ded3 0 Denunciar post Postado Janeiro 30, 2012 Hmm, entendi... Bom, acho que só restou mesmo a 5,7 e 8 que não são tão urgentes assim... Obrigado pelas dicas e respostas ai, é que eu sou novo ainda em C++, não entendo muita coisa, acho que vai ser a primeira linguagem que eu vou estudar pra valer, já que eu mexia com códigos simples em C e PHP, mas nunca estudei de verdade nenhuma das 2 e nunca fiz códigos orientados a objeto, então vou ver se acho alguns projetos open source por ai pra dar uma olhada no código, vou tentar começar pelo chromium... Compartilhar este post Link para o post Compartilhar em outros sites
Renato Utsch 24 Denunciar post Postado Janeiro 30, 2012 Boa sorte ^^ Lembre-se que, para poder ajudar realmente, você tem que, no mínimo, entender a linguagem. Um livro como o "C++ Primer, 4th edition" (NOT C++ Primer Plus) já é um ótimo começo. Abraços :D Compartilhar este post Link para o post Compartilhar em outros sites