Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este artigo descreve todas as alterações recentes do Visual Studio 2015 que remontam ao Visual Studio 2003 e, neste artigo, os termos "novo comportamento" ou "agora" referem-se ao Visual Studio 2015 e posterior. Os termos "comportamento antigo" e "antes" referem-se ao Visual Studio 2013 e versões anteriores.
Para obter informações sobre a versão mais recente do Visual Studio, consulte Novidades para C++ no Visual Studio e melhorias de conformidade C++ no Visual Studio.
Observação
Não há alterações de quebra binária entre o Visual Studio 2015 e o Visual Studio 2017.
Quando você atualiza para uma nova versão do Visual Studio, você pode encontrar erros de compilação e/ou tempo de execução no código que anteriormente compilado e executado corretamente. As alterações na nova versão que causam esses problemas são conhecidas como alterações de quebra e, normalmente, são exigidas por modificações no padrão da linguagem C++, assinaturas de função ou layout de objetos na memória.
Para evitar erros em tempo de execução difíceis de detetar e diagnosticar, recomendamos que você nunca vincule estaticamente a binários compilados usando uma versão diferente do compilador. Além disso, quando você atualizar um projeto EXE ou DLL, certifique-se de atualizar as bibliotecas às quais ele se vincula. Não passe tipos CRT (C Runtime) ou C++ Standard Library (C++ Standard Library) entre binários, incluindo DLLs, compilados usando versões diferentes do compilador. Para obter mais informações, consulte Possíveis erros ao passar objetos CRT através dos limites da DLL.
Você nunca deve escrever código que dependa de um layout específico para um objeto que não seja uma interface COM ou um objeto POD. Se você escrever esse código, então você deve garantir que ele funcione após a atualização. Para obter mais informações, consulte Portabilidade nos limites da ABI.
Além disso, melhorias contínuas na conformidade do compilador às vezes podem alterar como o compilador entende seu código-fonte existente. Por exemplo, você pode encontrar erros novos ou diferentes durante sua compilação, ou até mesmo diferenças comportamentais no código que foi criado anteriormente e parecia ser executado corretamente. Embora essas melhorias não sejam alterações significativas como as discutidas neste documento, talvez seja necessário fazer alterações no código-fonte para resolver esses problemas:
Alterações de conformidade do Visual Studio 2015
CRT (Biblioteca de tempo de execução C)
Alterações gerais
Binários refatorados
A Biblioteca CRT foi refatorada em dois binários diferentes: um CRT Universal (ucrtbase), que contém a maior parte da funcionalidade padrão, e um VC Runtime Library (vcruntime). A biblioteca vcruntime contém a funcionalidade relacionada ao compilador, como tratamento de exceções e intrínsecas. Se você estiver usando as configurações padrão do projeto, essa alteração não afetará você, pois o vinculador usa as novas bibliotecas padrão automaticamente. Se você definiu a propriedade Linker do projeto Ignore All Default Libraries como Yes ou está usando a
/NODEFAULTLIBopção linker na linha de comando, atualize sua lista de bibliotecas (na propriedade Additional Dependencies ) para incluir as novas bibliotecas refatoradas. Substitua a antiga biblioteca CRT (libcmt.lib,libcmtd.lib,msvcrt.libmsvcrtd.lib, ) pelas bibliotecas refatoradas equivalentes. Para cada uma das duas bibliotecas refatoradas, existem versões estáticas (.lib) e dinâmicas (.dll), e versões release (sem sufixo) e debug (com o sufixo "d"). As versões dinâmicas têm uma biblioteca de importação com a qual você se vincula. As duas bibliotecas refatoradas são a Universal CRT, especificamente ucrtbase.dll ou ucrtbase.lib, ucrtbased.dll ou ucrtbased.lib, e a biblioteca de tempo de execução VC,libvcruntime.libvcruntimeversão.dll,libvcruntimed.libe vcruntimedversão.dll. A versão no Visual Studio 2015 e no Visual Studio 2017 é 140. Consulte Recursos da biblioteca CRT.
<locale.h>
localeconvA
localeconvfunção declarada em locale.h agora funciona corretamente quando a localização por thread está habilitada. Em versões anteriores da biblioteca, essa função retornava oslconvdados para a localidade global, não a localidade do thread.Se você usar localidades por thread, deverá verificar o uso do
localeconv. Se o código assumir que oslconvdados retornados são para a localidade global, você deve corrigi-lo.
<math.h>
Sobrecargas das funções da biblioteca matemática em C++
Em versões anteriores,
<math.h>definia algumas, mas não todas, as sobrecargas C++ para as funções da biblioteca matemática. O resto da sobrecarga estava no<cmath>cabeçalho. Código que apenas incluía<math.h>pode ter problemas com a resolução de sobrecarga de função. Agora, as sobrecargas C++ foram removidas de<math.h>e só são encontradas em<cmath>.Para resolver erros, inclua
<cmath>para obter as declarações das funções que foram removidas do<math.h>. Estas funções foram movidas:-
double abs(double)efloat abs(float) -
double pow(double, int),float pow(float, float),float pow(float, int),long double pow(long double, long double),long double pow(long double, int) -
floatelong doubleversões de funções de ponto flutuante,acos,acosh,asin,asinh,atan,atanh,atan2,cbrt,ceil,copysign,cos,cosh,erf,erfc,exp,exp2,expm1,fabs,fdim,floor,fma,fmax,fmin,fmod,frexp,hypot,ilogb,ldexp,lgamma,llrint,llround,log,log10,log1p,log2,lrint,lround,modf,nearbyint,nextafter,nexttoward,remainder,remquo,rint,round,scalbln,scalbn,sin,sinh,sqrt,tan,tanh,tgamma, etrunc
Se você tiver um código que usa
abscom um tipo de ponto flutuante que inclui apenas o<math.h>cabeçalho, as versões de ponto flutuante não estarão mais disponíveis. Agora a chamada resolve-se paraabs(int), mesmo com um argumento de ponto flutuante, o que produz o erro:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of dataA correção para esse aviso é substituir a chamada para
abspor uma versão de ponto flutuante doabs, comofabspara um argumento duplo oufabsfpara um argumento float, ou incluir o<cmath>cabeçalho e continuar a usarabs.-
Conformidade de ponto flutuante
Muitas mudanças na biblioteca de matemática foram feitas para melhorar a conformidade com as especificações IEEE-754 e C11 Anexo F com relação a entradas de casos especiais, como NaNs e infinities. Por exemplo, entradas NaN silenciosas, que muitas vezes eram tratadas como erros em versões anteriores da biblioteca, não são mais tratadas como erros. Ver norma IEEE 754 e anexo F da norma C11.
Essas alterações não causarão erros em tempo de compilação, mas podem fazer com que os programas se comportem de forma diferente e mais correta de acordo com o padrão.
FLT_ROUNDS
No Visual Studio 2013, a macro FLT_ROUNDS foi expandida para uma expressão constante, o que estava incorreto porque o modo de arredondamento é configurável em tempo de execução, por exemplo, chamando fesetround. A macro FLT_ROUNDS é agora dinâmica e reflete corretamente o modo de arredondamento atual.
<new> e <new.h>
newedeleteEm versões anteriores da biblioteca, as funções new e delete do operador definido pela implementação eram exportadas da DLL da biblioteca de tempo de execução (por exemplo, msvcr120.dll). Essas funções de operadores agora estão sempre vinculadas estaticamente nos seus binários, mesmo ao usar as DLLs da biblioteca de execução.
Esta não é uma alteração significativa para código nativo ou misto (
/clr), no entanto, para código compilado como /clr:pure, essa alteração pode fazer com que seu código falhe na compilação. Se você compilar o código como/clr:pure, talvez seja necessário adicionar#include <new>ou#include <new.h>contornar erros de compilação devido a essa alteração. A/clr:pureopção foi preterida no Visual Studio 2015 e não tem suporte no Visual Studio 2017. O código que precisa ser "puro" deve ser portado para C#.
<process.h>
_beginthreade_beginthreadexAs
_beginthreadfunções e_beginthreadexagora contêm uma referência ao módulo no qual o procedimento de thread é definido para a duração do thread. Isso ajuda a garantir que os módulos não sejam descarregados até que um thread seja executado até a conclusão.
<stdarg.h>
va_starte tipos de referênciaAo compilar código C++,
va_startagora valida em tempo de compilação que o argumento passado para ele não é do tipo de referência. Argumentos de tipo de referência são proibidos pelo padrão C++.
<stdio.h> e <conio.h>
A família de funções printf e scanf agora é definida em linha.
As definições de todas as funções
printfescanfforam incorporadas diretamente em<stdio.h>,<conio.h>e outros cabeçalhos CRT. Essa alteração disruptiva leva a um erro de ligação (LNK2019, símbolo externo não resolvido) para programas que declararam estas funções localmente sem incluir os cabeçalhos adequados do CRT. Se possível, você deve atualizar o código para incluir os cabeçalhos CRT (ou seja, adicionar#include <stdio.h>) e as funções embutidas, mas se você não quiser modificar seu código para incluir esses arquivos de cabeçalho, uma solução alternativa é adicionarlegacy_stdio_definitions.libà sua entrada do vinculador.Para adicionar essa biblioteca à entrada do vinculador no IDE, abra o menu de contexto do nó do projeto, escolha Propriedades, na caixa de diálogo Propriedades do projeto , escolha Vinculador e edite a Entrada do vinculador para adicionar
legacy_stdio_definitions.libà lista separada por ponto-e-vírgula.Se o seu projeto estiver vinculado a bibliotecas estáticas que foram compiladas com uma versão do Visual Studio anterior a 2015, o linker pode reportar um símbolo externo não resolvido. Estes erros podem fazer referência a definições internas de
_iob,_iob_funcou a importações conexas para determinadas<stdio.h>funções sob a forma de imp*. A Microsoft recomenda que você recompile todas as bibliotecas estáticas com a versão mais recente do compilador C++ e bibliotecas quando você atualizar um projeto. Se a biblioteca for uma biblioteca de terceiros para a qual a fonte não está disponível, você deve solicitar um binário atualizado do terceiro ou encapsular seu uso dessa biblioteca em uma DLL separada que você compila com a versão mais antiga do compilador e das bibliotecas.Advertência
Se você estiver vinculando com o Windows SDK 8.1 ou anterior, poderá encontrar esses erros de símbolo externo não resolvidos. Nesse caso, você deve resolver o erro adicionando legacy_stdio_definitions.lib à entrada do vinculador, conforme descrito anteriormente.
Para solucionar erros de símbolos não resolvidos, você pode tentar usar
dumpbin.exepara examinar os símbolos definidos em um binário. Tente a seguinte linha de comando para exibir símbolos definidos em uma biblioteca.dumpbin.exe /LINKERMEMBER somelibrary.librecebe e _getws
As funções get e _getws foram removidas. A função gets foi removida da Biblioteca Padrão C em C11 porque não pode ser usada com segurança. A função _getws era uma extensão da Microsoft que era equivalente a gets, mas para cadeias de caracteres largas. Como alternativas a essas funções, considere o uso de fgets, fgetws, gets_s e _getws_s.
_cgets e _cgetws
As funções _cgets e _cgetws foram removidas. Como alternativas a essas funções, considere o uso de _cgets_s e _cgetws_s.
Formatação de Infinito e NaN
Em versões anteriores, infinities e NaNs seriam formatados usando um conjunto de strings sentinel específicas do MSVC.
Infinito: 1.#INF
NaN Quieto: 1.#QNAN
Sinalização NaN: 1.#SNAN
NaN indefinido: 1.#IND
Qualquer um desses formatos pode ter sido precedido por um sinal e pode ter sido formatado de forma ligeiramente diferente, dependendo da largura e precisão do campo (às vezes com efeitos incomuns, por exemplo
printf("%.2f\n", INFINITY), imprimiria 1,#J porque o #INF seria "arredondado" para uma precisão de 2 dígitos). A C99 introduziu novos requisitos sobre a forma como as infinidades e os NaNs devem ser formatados. A implementação do MSVC agora está em conformidade com esses requisitos. As novas cadeias de caracteres são as seguintes:Infinito: ∞
NaN tranquilo: nan
Sinalização NaN: nan(snan)
NaN indefinido: nan(ind)
Qualquer um deles pode ser precedido por um sinal. Se for usado um especificador de formato em maiúsculas (%F em vez de %f), então as cadeias de caracteres são impressas em letras maiúsculas (
INFem vez deinf), como é necessário.As funções scanf foram modificadas para analisar essas novas strings, permitindo agora que essas strings sejam processadas de ida e de volta através do
printfescanf.Formatação e análise de ponto flutuante
Novos algoritmos de formatação e análise de ponto flutuante foram introduzidos para melhorar a correção. Essa alteração afeta as famílias de funções printf e scanf e funções como strtod.
Os algoritmos de formatação antigos geravam apenas um número limitado de dígitos e, em seguida, preenchiam as casas decimais restantes com zero. Eles geralmente podiam gerar cadeias de caracteres que voltariam ao valor original do ponto flutuante, mas não eram ótimas se você quisesse o valor exato (ou a representação decimal mais próxima dele). Os novos algoritmos de formatação geram quantos dígitos forem necessários para representar o valor (ou para preencher a precisão especificada). Como exemplo da melhoria; Considere os resultados ao imprimir uma grande potência de dois:
printf("%.0f\n", pow(2.0, 80))Saída antiga:
1208925819614629200000000Nova saída:
1208925819614629174706176Os antigos algoritmos de análise considerariam apenas até 17 dígitos significativos da cadeia de entrada e descartariam o restante dos dígitos. Esta abordagem é suficiente para gerar uma aproximação do valor representado pela cadeia de caracteres, e o resultado é geralmente muito próximo do resultado arredondado corretamente. A nova implementação considera todos os dígitos presentes e produz o resultado arredondado corretamente para todas as entradas (até 768 dígitos de comprimento). Além disso, estas funções respeitam agora o modo de arredondamento, que pode ser controlado por meio de fesetround. Isso é potencialmente uma mudança de comportamento significativa porque essas funções podem produzir resultados diferentes. Os novos resultados são sempre mais corretos do que os resultados antigos.
Análise de ponto flutuante hexadecimal e infinito/NaN
Os algoritmos de análise de ponto flutuante agora analisarão cadeias de caracteres de ponto flutuante hexadecimais (como as geradas pelos especificadores de formato %a e %A printf) e todas as cadeias de caracteres infinito e NaN geradas pelas
printffunções, conforme descrito acima.%A e %a preenchimento zero
Os especificadores de formato %a e %A formatam um número de ponto flutuante como uma mantissa hexadecimal e expoente binário. Em versões anteriores, as funções
printfpreenchiam incorretamente com zeros as strings. Por exemplo,printf("%07.0a\n", 1.0)imprimiria 00x1p+0, onde deveria imprimir 0x01p+0. Esta falha foi corrigida.precisão%A e %a
A precisão padrão dos especificadores de formato %A e %a era 6 nas versões anteriores da biblioteca. A precisão padrão agora é 13 para conformidade com o padrão C.
Esta é uma alteração no comportamento em tempo de execução na saída de qualquer função que utilize uma cadeia de caracteres de formato com %A ou %a. No comportamento antigo, a saída usando o especificador %A pode ser "1.1A2B3Cp+111". Agora, a saída para o mesmo valor é "1.1A2B3C4D5E6F7p+111". Para obter o comportamento antigo, você pode especificar a precisão, por exemplo, %.6A. Consulte Especificação de precisão.
%F especificador
O especificador de formato/conversão %F é agora suportado. É funcionalmente equivalente ao especificador de formato %f, exceto que infinitos e NaNs são formatados com letras maiúsculas.
Em versões anteriores, a implementação usava para interpretar F e N como modificadores de comprimento. Esse comportamento remonta à era dos espaços de endereçamento segmentados: esses modificadores de comprimento eram usados para indicar ponteiros de longe e de perto, respectivamente, como em %Fp ou %Ns. Esse comportamento foi removido. Se %F for encontrada, ela será tratada como o especificador de formato %F; Se %N for encontrado, ele será tratado como um parâmetro inválido.
Formatação de expoente
Os especificadores de formato %e e %E formatam um número de ponto flutuante como uma mantissa decimal e um expoente. Os especificadores de formato %g e %G também formatam números nesta forma em alguns casos. Nas versões anteriores, o CRT sempre gerava strings com expoentes de três dígitos. Por exemplo,
printf("%e\n", 1.0)imprimiria 1,000000e+000, o que estava incorreto. C exige que, se o expoente for representável usando apenas um ou dois dígitos, então apenas dois dígitos devem ser impressos.No Visual Studio 2005, uma opção de conformidade global foi adicionada: _set_output_format. Um programa pode chamar essa função com o argumento _TWO_DIGIT_EXPONENT, para permitir a impressão de expoentes conformes. O comportamento padrão foi alterado para o modo de impressão expoente em conformidade com os padrões.
Validação de cadeia de caracteres de formato
Em versões anteriores, as
printffunções escanfaceitavam silenciosamente muitas cadeias de caracteres de formato inválidas, às vezes com efeitos incomuns. Por exemplo, %hlhlhld seriam tratados como %d. Todas as cadeias de caracteres de formato inválidas agora são tratadas como parâmetros inválidos.Validação de cadeia de caracteres do modo fopen
Em versões anteriores, a
fopenfamília de funções aceitava silenciosamente algumas cadeias de caracteres de modo inválidas, comor+b+. Cadeias de caracteres de modo inválido agora são detetadas e tratadas como parâmetros inválidos.Modo _O_U8TEXT
A função _setmode agora relata corretamente o modo para fluxos abertos no modo _O_U8TEXT. Em versões anteriores da biblioteca, reportava tais fluxos como sendo abertos em _O_WTEXT.
Esta é uma alteração significativa se o seu código interpretar o modo _O_WTEXT para fluxos em que a codificação é UTF-8. Se a sua aplicação não suportar UTF_8, considere adicionar suporte para esta codificação cada vez mais comum.
snprintf e vsnprintf
As funções snprintf e vsnprintf agora estão implementadas. O código mais antigo geralmente fornecia definições de versões de macro dessas funções porque elas não foram implementadas pela biblioteca CRT, mas não são mais necessárias em versões mais recentes. Se snprintf ou vsnprintf for definido como uma macro antes de incluir
<stdio.h>, a compilação agora falhará com um erro que indica onde a macro foi definida.Normalmente, a correção para este problema é excluir todas as declarações de
snprintfouvsnprintfno código do usuário.tmpnam gera nomes de arquivos utilizáveis
Em versões anteriores, as funções
tmpnametmpnam_sgeravam nomes de ficheiro na raiz da unidade (como \sd3c.). Essas funções agora geram caminhos de nome de arquivo utilizáveis em um diretório temporário.FILE Encapsulamento
Nas versões anteriores, o tipo completo de FILE era definido publicamente em
<stdio.h>, de modo que era possível que o código do usuário chegasse a um FILE e modificasse seus internos. A biblioteca foi alterada para ocultar detalhes de implementação. Como parte dessa alteração, FILE como definido em<stdio.h>agora é um tipo opaco e seus membros são inacessíveis de fora do próprio CRT._outp e _inp
As funções _outp, _outpw, _outpd, _inp, _inpw e _inpd foram removidas.
<stdlib.h>, <malloc.h>e <sys/stat.h>
strtof e wcstof
As funções
strtofewcstoffalharam em definirerrnocomo ERANGE quando o valor não era representável como um flutuante. Este erro era específico destas duas funções; asstrtodfunções ,wcstod,strtoldewcstoldnão foram afetadas. Este problema foi corrigido e é uma alteração radical no tempo de execução.Funções de atribuição alinhadas
Nas versões anteriores, as funções de alocação alinhadas (
_aligned_malloc,_aligned_offset_malloc, etc.) aceitavam silenciosamente solicitações de um bloco com um alinhamento de 0. O alinhamento solicitado deve ser uma potência de dois, o que não é verdade para o valor zero. Um alinhamento solicitado de 0 é agora tratado como um parâmetro inválido. Este problema foi corrigido e é uma alteração radical no tempo de execução.Funções de pilha
As
_heapaddfunções ,_heapsete_heapusedforam removidas. Essas funções não funcionam desde que o CRT foi atualizado para usar o heap do Windows.pilha pequena
A
smallheapopção de link foi removida. Consulte Opções de link._stat
A
_statfamília de funções usaCreateFileno Visual Studio 2015, em vez deFindFirstFile, assim como no Visual Studio 2013 e anteriores. Isso significa que num caminho que termina com_staté bem-sucedido se o caminho se refere a um diretório, diferente de antes, quando a função erraria comerrnodefinido paraENOENT.
<string.h>
wcstokA assinatura da
wcstokfunção foi alterada para corresponder ao que é exigido pelo Padrão C. Em versões anteriores da biblioteca, a assinatura desta função era:wchar_t* wcstok(wchar_t*, wchar_t const*)Utiliza um contexto interno em cada thread para rastrear o estado entre chamadas, tal como é feito para
strtok. A função agora tem a assinaturawchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)e requer que o chamador passe o contexto como um terceiro argumento para a função.Uma nova
_wcstokfunção foi adicionada com a assinatura antiga para facilitar a portabilidade. Ao compilar código C++, também existe uma sobrecarga inline dewcstokque mantém a assinatura antiga. Essa sobrecarga é declarada como obsoleta. No código C, pode definir define_CRT_NON_CONFORMING_WCSTOK para fazer com que_wcstokseja usado no lugar dewcstok.
<time.h>
relógio
Em versões anteriores, a
clockfunção foi implementada usando a APIGetSystemTimeAsFileTimedo Windows. Com esta implementação, a função de relógio era sensível ao tempo do sistema e, portanto, não era necessariamente monotônica. A função de relógio foi reimplementada em termos deQueryPerformanceCountere agora é monotônica.fstat e _utime
Nas versões anteriores, as funções
_stat,fstate_utimelidam com o horário de verão incorretamente. Antes do Visual Studio 2013, todas essas funções ajustavam incorretamente os horários padrão como se estivessem no horário de luz do dia.No Visual Studio 2013, o problema foi corrigido na família de funções
_stat, mas os problemas semelhantes nas famílias de funçõesfstate_utimenão foram corrigidos. Esta correção parcial levou a problemas devido à inconsistência entre as funções. As famílias de funçõesfstate_utimeforam agora corrigidas, pelo que todas estas funções lidam com o horário de verão de forma correta e consistente.ASCTIME
Nas versões anteriores, a função
asctimepreenchia dias de um dígito com um zero à esquerda, por exemplo:Fri Jun 06 08:00:00 2014. A especificação exige que esses dias sejam preenchidos com um espaço em branco antes, como emFri Jun 6 08:00:00 2014. Esse problema foi corrigido.strftime e wcsftime
As
strftimefunções ewcsftimeagora suportam os especificadores de formato %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %ue %V. Além disso, os modificadores E e O são analisados, mas ignorados.O especificador de formato %c é especificado como produzindo uma "representação de data e hora apropriada" para a localidade atual. Na localidade C, essa representação deve ser a mesma que
%a %b %e %T %Y, a mesma forma que é produzida porasctime. Em versões anteriores, o especificador de formato %c formatava incorretamente as horas usando a representaçãoMM/DD/YY HH:MM:SS. Esse problema foi corrigido.TimeSpec e TIME_UTC
O
<time.h>cabeçalho agora define otimespectipo e atimespec_getfunção do padrão C11. Além disso, a macro TIME_UTC, para uso com atimespec_getfunção, agora está definida. Esta atualização é uma alteração de ruptura para o código que tem uma definição conflitante para qualquer destes identificadores.CLOCKS_PER_SEC
A macro CLOCKS_PER_SEC agora se expande para um inteiro do tipo
clock_t, conforme exigido pela linguagem C.
Biblioteca padrão C++
Para habilitar novas otimizações e verificações de depuração, a implementação do Visual Studio da biblioteca padrão C++ intencionalmente quebra a compatibilidade binária de uma versão para a próxima. Portanto, quando a biblioteca padrão C++ é usada, arquivos de objeto e bibliotecas estáticas que são compilados usando versões diferentes não podem ser misturados em um binário (EXE ou DLL) e objetos C++ Standard Library não podem ser passados entre binários que são compilados usando versões diferentes. Essa mistura gera erros de vinculação devido a incompatibilidades do _MSC_VER. (_MSC_VER é a macro que contém a versão principal do compilador — por exemplo, 1800 para Visual Studio 2013.) Essa verificação não pode detetar a mistura de DLL e não pode detetar a mistura que envolve o Visual Studio 2008 ou anterior.
A biblioteca padrão do C++ inclui arquivos
Algumas alterações foram feitas na estrutura de inclusão nos cabeçalhos da biblioteca padrão C++. Os cabeçalhos da Biblioteca Padrão do C++ podem ser incluídos uns aos outros de maneiras não especificadas. Em geral, você deve escrever seu código para que ele inclua cuidadosamente todos os cabeçalhos de que precisa de acordo com o padrão C++ e não dependa de quais cabeçalhos da Biblioteca Padrão C++ incluem quais outros cabeçalhos da Biblioteca Padrão C++. Isso torna o código portátil entre versões e plataformas. Pelo menos duas alterações de cabeçalho no Visual Studio 2015 afetam o código do usuário. Primeiro,
<string>não inclui<iterator>mais . Em segundo lugar,<tuple>agora declarastd::arraysem incluir todo o<array>, o que pode quebrar o código através da seguinte combinação de construções de código: o seu código possui uma variável chamada "array", e você usa uma diretiva "using namespace std;", e inclui um cabeçalho da Biblioteca Padrão C++ (como<functional>) que inclui<tuple>, que agora declarastd::array.steady_clock
A implementação de
<chrono>nosteady_clockfoi alterada para atender aos requisitos do Standard C++ para estabilidade e monotonicidade.steady_clockagora é baseado emQueryPerformanceCounterehigh_resolution_clockagora é um typedef desteady_clock. Como resultado, no Visual Studiosteady_clock::time_pointagora é um typedef parachrono::time_point<steady_clock>, no entanto, este não é necessariamente o caso para outras implementações.alocadores e const
Passámos agora a exigir que as comparações de igualdade e desigualdade de alocadores aceitem argumentos const em ambos os lados. Se seus alocadores definirem esses operadores assim,
bool operator==(const MyAlloc& other)Em seguida, deve atualizá-los e declará-los como membros da CONST:
bool operator==(const MyAlloc& other) constelementos constantes
O padrão C++ sempre proibiu contêineres de elementos const (como
vector<const T>ouset<const T>). O Visual Studio 2013 e versões anteriores aceitavam esses contêineres. Na versão atual, esses contêineres não são compilados.std::alocador::d eallocate
No Visual Studio 2013 e anteriores,
std::allocator::deallocate(p, n)ignorou o argumento passado para n. O padrão C++ sempre exigiu que n fosse igual ao valor passado como o primeiro argumento para a invocação de , que retornavaallocatep. No entanto, na versão atual, o valor de n é inspecionado. O código que passa argumentos para n que diferem do que o padrão exige pode falhar no tempo de execução.hash_map e hash_set
Os arquivos
<hash_map>de cabeçalho não padrão e<hash_set>foram preteridos no Visual Studio 2015 e serão removidos em uma versão futura. Use<unordered_map>e<unordered_set>em vez disso.Comparadores e operador()
Os contentores associativos (a família
<map>) agora exigem que os seus comparadores tenham operadores de chamada de função constante. O código a seguir em uma declaração de classe de comparação agora não consegue compilar:bool operator()(const X& a, const X& b)Para resolver esse erro, altere a declaração de função para:
bool operator()(const X& a, const X& b) constCaracterísticas do tipo
Os nomes antigos para características de tipo de uma versão anterior do padrão de rascunho C++ foram removidos. Eles foram alterados em C++11 e foram atualizados para os valores C++11 no Visual Studio 2015. A tabela a seguir mostra os nomes antigos e novos.
Nome antigo Novo nome adicionar_referência add_lvalue_reference tem_construtor_padrão é_construível_por_defeito tem_construtor_de_cópia é_copiavelmente_construível tem_construtor_de_movimento é_móvel_construível has_nothrow_constructor (construtor que não lança exceções) is_nothrow_default_constructible (verifica se pode ser construído sem lançar exceções) tem_construtor_padrão_sem_exceções is_nothrow_default_constructible (verifica se pode ser construído sem lançar exceções) has_nothrow_copy is_nothrow_copy_constructible tem_constructor_de_cópia_sem_exceções is_nothrow_copy_constructible tem_construtor_de_movimento_sem_exceções is_nothrow_move_constructible has_nothrow_assign is_nothrow_copy_assignable tem_assignment_por_cópia_sem_throw is_nothrow_copy_assignable atributo_sem_exceção_na_afetação_por_movimento is_nothrow_move_assignable (verifica se um tipo possui um operador de atribuição de movimento trivial que não lança exceções) Construtor_Trivialpresente is_trivially_default_constructible (é_trivialmente_predefinido_construível) tem_construtor_padrão_trivial is_trivially_default_constructible (é_trivialmente_predefinido_construível) tem_cópia_trivial is_trivially_copy_constructible has_trivial_move_constructor (possui construtor de movimentação trivial) é_trivialmente_construível_com_movimento atribuição_trivial é trivialmente atribuível por cópia has_trivial_move_assign is_trivially_move_assignable tem_destrutor_trivial is_trivially_destructible políticas launch::any e launch::sync
As políticas não-padrão
launch::anyelaunch::syncforam removidas. Em vez disso, paralaunch::any, uselaunch:async | launch:deferred. Paralaunch::sync, uselaunch::deferred. Consulte launch Enumeration.
MFC e ATL
Classes de base da Microsoft (MFC)
não está mais incluído em uma instalação "típica" do Visual Studio devido ao seu grande tamanho. Para instalar o MFC, escolha a opção Instalação personalizada na instalação do Visual Studio 2015. Se você já tiver o Visual Studio 2015 instalado, poderá instalar o MFC executando a instalação do Visual Studio novamente. Escolha a opção de instalação personalizada e, em seguida, escolha Microsoft Foundation Classes. Você pode executar a instalação do Visual Studio a partir dos programas e recursos de controle do painel de controle ou da mídia de instalação.
O Visual C++ Redistributable Package ainda inclui esta biblioteca.
Tempo de Execução de Concorrência
Macro de rendimento do Windows.h em conflito com simultaneidade::Contexto::Rendimento
Anteriormente, o Concurrency Runtime usava
#undefpara desdefinir a macro Yield para evitar conflitos entre a macro Yield definida em Windows.h e a funçãoconcurrency::Context::Yield. Esta#undeffoi removida e uma nova chamada de API equivalente não conflitante, concurrency::Context::YieldExecution, foi adicionada. Para contornar conflitos com Yield, você pode atualizar seu código para chamar aYieldExecutionfunção em vez disso ou cercar o nome daYieldfunção com parênteses em sites de chamada, como no exemplo a seguir:(concurrency::Context::Yield)();
Melhorias de conformidade do compilador no Visual Studio 2015
Ao atualizar o código de versões anteriores, você também pode encontrar erros de compilador que são devido a melhorias de conformidade feitas no Visual Studio 2015. Essas melhorias não quebram a compatibilidade binária de versões anteriores do Visual Studio, mas podem produzir erros de compilador onde nenhum foi emitido antes. Para obter mais informações, consulte Visual C++ What's New 2003 to 2015.
No Visual Studio 2015, melhorias contínuas na conformidade do compilador às vezes podem alterar como o compilador entende seu código-fonte existente. Como resultado, você pode encontrar erros novos ou diferentes durante sua compilação, ou até mesmo diferenças comportamentais no código que foi criado anteriormente e parecia ser executado corretamente.
Felizmente, essas diferenças têm pouco ou nenhum impacto na maioria do seu código-fonte. Quando o código-fonte ou outras alterações são necessárias para resolver essas diferenças, as correções tendem a ser pequenas e diretas. Incluímos muitos exemplos de código-fonte anteriormente aceitável que podem precisar ser alterados (antes) e as correções para corrigi-los (depois).
Embora essas diferenças possam afetar seu código-fonte ou outros artefatos de compilação, elas não afetam a compatibilidade binária entre atualizações para versões do Visual Studio. Uma alteração crítica é mais grave e pode afetar a compatibilidade binária, mas esse tipo de quebra de compatibilidade binária só ocorre entre as versões principais do Visual Studio, por exemplo, entre o Visual Studio 2013 e o Visual Studio 2015. Para obter informações sobre as alterações recentes que ocorreram entre o Visual Studio 2013 e o Visual Studio 2015, consulte Alterações de conformidade do Visual Studio 2015.
Melhorias de conformidade no Visual Studio 2015
opção /Zc:forScope-
A opção
/Zc:forScope-do compilador foi preterida e será removida em uma versão futura.Command line warning D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future releaseNormalmente, esta opção foi usada para permitir código não padrão que usa variáveis de loop após o ponto onde, de acordo com o padrão, elas deveriam ter saído do escopo. Só foi necessário quando você compilou com a
/Zaopção, já que sem/Za, o uso de uma variável for loop após o fim do loop é sempre permitido. Se você não se importa com a conformidade de padrões (por exemplo, se seu código não se destina a ser portátil para outros compiladores), você pode desativar a/Zaopção (ou definir a propriedade Desativar extensões de idioma como Não). Se você se preocupa em escrever código portátil e em conformidade com os padrões, você deve reescrever seu código para que ele esteja em conformidade com o padrão, movendo a declaração de tais variáveis para um ponto fora do loop.// C2065 expected int main() { // Uncomment the following line to resolve. // int i; for (int i = 0; i < 1; i++); i = 20; // i has already gone out of scope under /Za }/Zgopção do compiladorA
/Zgopção do compilador (Gerar protótipos de função) não está mais disponível. Esta opção do compilador foi preterida anteriormente.Não é mais possível executar testes de unidade com C++/CLI a partir da linha de comando com mstest.exe. Em vez disso, use vstest.console.exe. Consulte VSTest.Console.exe opções de linha de comando.
palavra-chave mutável
O
mutableespecificador de classe de armazenamento não é mais permitido em locais onde anteriormente era compilado sem erro. Agora, o compilador dá erro C2071 (classe de armazenamento ilegal). De acordo com o padrão, omutableespecificador pode ser aplicado apenas a nomes de membros de dados de classe, e não pode ser aplicado a nomes declarados const ou estáticos, e não pode ser aplicado a membros de referência.Por exemplo, considere o seguinte código:
struct S { mutable int &r; };As versões anteriores do compilador aceitavam isso, mas agora o compilador dá o seguinte erro:
error C2071: 'S::r': illegal storage classPara corrigir o erro, remova a palavra-chave redundante
mutable.char_16_t e char32_t
Você não pode mais usar
char16_touchar32_tcomo pseudónimos em umtypedef, porque esses tipos agora são considerados incorporados. Era comum que usuários e autores de bibliotecas definissemchar16_techar32_tcomo pseudônimos deuint16_teuint32_t, respectivamente.#include <cstdint> typedef uint16_t char16_t; //C2628 typedef uint32_t char32_t; //C2628 int main(int argc, char* argv[]) { uint16_t x = 1; uint32_t y = 2; char16_t a = x; char32_t b = y; return 0; }Para atualizar seu código, remova as
typedefdeclarações e renomeie quaisquer outros identificadores que colidam com esses nomes.Parâmetros de modelo não tipo
Determinado código que envolve parâmetros de modelo que não são do tipo agora é verificado corretamente quanto à compatibilidade de tipo quando você fornece argumentos de modelo explícitos. Por exemplo, o código a seguir compilado sem erro em versões anteriores do Visual Studio.
struct S1 { void f(int); void f(int, int); }; struct S2 { template <class C, void (C::*Function)(int) const> void f() {} }; void f() { S2 s2; s2.f<S1, &S1::f>(); }O compilador atual dá corretamente um erro, porque o tipo de parâmetro do modelo não corresponde ao argumento do modelo (o parâmetro é um ponteiro para um membro constante, mas a função f é não constante):
error C2893: Failed to specialize function template 'void S2::f(void)'note: With the following template arguments:note: 'C=S1'note: 'Function=S1::f'Para resolver esse erro em seu código, certifique-se de que o tipo do argumento de modelo que você usa corresponde ao tipo declarado do parâmetro de modelo.
__declspec(align)O compilador já não aceita
__declspec(align)em funções. Essa construção sempre foi ignorada, mas agora produz um erro de compilador.error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarationsPara corrigir esse problema, remova
__declspec(align)da declaração de função. Como não surtiu efeito, removê-lo não muda nada.Tratamento de exceções
Há algumas mudanças no tratamento de exceções. Em primeiro lugar, os objetos de exceção têm de ser copiáveis ou móveis. O código a seguir compilado no Visual Studio 2013, mas não compilado no Visual Studio 2015:
struct S { public: S(); private: S(const S &); }; int main() { throw S(); // error }O problema é que o construtor de cópia é privado, portanto, o objeto não pode ser copiado como acontece no processo normal de manipulação de uma exceção. O mesmo se aplica quando o construtor copy é declarado
explicit.struct S { S(); explicit S(const S &); }; int main() { throw S(); // error }Para atualizar seu código, certifique-se de que o construtor de cópia para seu objeto de exceção é
publice não marcadoexplicit.Capturar uma exceção por valor também requer que o objeto de exceção seja copiável. O código a seguir compilado no Visual Studio 2013, mas não compilado no Visual Studio 2015:
struct B { public: B(); private: B(const B &); }; struct D : public B {}; int main() { try { } catch (D d) // error { } }Você pode corrigir esse problema alterando o tipo de parâmetro para o
catchpara uma referência.catch (D& d) { }Literais de cadeia de caracteres seguidos por macros
O compilador agora suporta literais definidos pelo usuário. Como consequência, literais de string seguidos por macros sem espaço em branco entre eles são interpretados como literais definidos pelo utilizador, o que pode causar erros ou resultados inesperados. Por exemplo, em compiladores anteriores, o seguinte código compilado com êxito:
#define _x "there" char* func() { return "hello"_x; } int main() { char * p = func(); return 0; }O compilador interpretou este código como um literal de cadeia "hello", seguido por uma macro, que é expandida em "there", e então os dois literais de cadeia foram concatenados num só. No Visual Studio 2015, o compilador interpreta essa sequência como um literal definido pelo usuário, mas como não há nenhum literal
_xdefinido pelo usuário correspondente, ele fornece um erro.error C3688: invalid literal suffix '_x'; literal operator or literal operator template 'operator ""_x' not found note: Did you forget a space between the string literal and the prefix of the following string literal?Para corrigir esse problema, adicione um espaço entre a cadeia de caracteres literal e a macro.
Literais de strings adjacentes
Da mesma forma que no anterior, devido a alterações relacionadas na análise de strings, literais de cadeia de caracteres adjacentes (literais de cadeia de caracteres largos ou de caracteres estreitos) sem qualquer espaço em branco foram interpretados como uma única cadeia de caracteres concatenada em versões anteriores do Visual C++. No Visual Studio 2015, agora você deve adicionar espaço em branco entre as duas cadeias de caracteres. Por exemplo, o seguinte código deve ser alterado:
char * str = "abc""def";Para corrigir esse problema, adicione um espaço entre as duas cadeias de caracteres:
char * str = "abc" "def";Posicionamento novo e exclusão
Uma alteração foi feita no operador para colocá-lo em conformidade com o
deletepadrão C++14. Detalhes da mudança de padrões podem ser encontrados em C++ Sized Deallocation. As alterações adicionam uma forma do operador globaldeleteque usa um parâmetro size. A alteração crítica é que se anteriormente estavas a usar um operadordeletecom a mesma assinatura (para corresponder a um operador placement new), irás receber um erro de compilação (C2956, que ocorre no ponto em que o placement new é utilizado, uma vez que essa é a posição no código onde o compilador tenta identificar um operadordeletecorrespondente apropriado).A função
void operator delete(void *, size_t)era um operador placement delete correspondente à função placement newvoid * operator new(size_t, size_t)em C++11. Com o tamanho C++14 deallocation, essa função de exclusão agora é uma função de desalocação usual (operador globaldelete). O padrão requer que, se o uso de um novo posicionamento procura uma função de exclusão correspondente e encontra uma função de desalocação usual, o programa está mal formado.Por exemplo, suponha que o seu código defina tanto um placement new como um placement delete:
void * operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;O problema ocorre devido à correspondência nas assinaturas de função entre um operador placement delete que definiu, e o novo operador global dimensionado
delete. Considere se tu podes usar um tipo diferente desize_tpara qualquer placement new edeleteoperadores. O tipo desize_ttypedefdepende do compilador; no MSVC, é umtypedefparaunsigned int. Uma boa solução é usar um tipo enumerado como este:enum class my_type : size_t {};Em seguida, altere sua definição de posicionamento novo e
deleteuse esse tipo como o segundo argumento em vez desize_t. Você também precisará atualizar as chamadas para placement new para passar o novo tipo (por exemplo, usandostatic_cast<my_type>para converter a partir do valor inteiro) e atualizar a definição denewedeletepara fazer o casting de volta para o tipo inteiro. Você não precisa usar umenumpara isso, um tipo de classe com umsize_tmembro também funcionaria.Uma solução alternativa é que você pode ser capaz de eliminar completamente o placement new. Se o seu código usa placement new para implementar um pool de memória onde o argumento de posicionamento é o tamanho do objeto que está a ser alocado ou eliminado, o recurso de desalocação dimensionada pode ser adequado para substituir o seu próprio código de pool de memória personalizado, e pode simplesmente usar o seu próprio operador de dois argumentos
deleteem vez das funções de posicionamento.Se você não quiser atualizar seu código imediatamente, você pode reverter para o comportamento antigo usando a opção
/Zc:sizedDealloc-de compilador . Se você usar essa opção, as funções de exclusão de dois argumentos não existirão e não causarão um conflito com o operador de exclusão de posicionamento .Membros de dados da União
Os dados dos membros dos sindicatos já não podem ter tipos de referência. O código a seguir compilado com êxito no Visual Studio 2013, mas produz um erro no Visual Studio 2015.
union U1 { const int i; }; union U2 { int & i; }; union U3 { struct { int & i; }; };O código anterior produz os seguintes erros:
test.cpp(67): error C2625: 'U2::i': illegal union member; type 'int &' is reference type test.cpp(70): error C2625: 'U3::i': illegal union member; type 'int &' is reference typePara resolver esse problema, altere os tipos de referência para um ponteiro ou um valor. Alterar o tipo para um ponteiro requer alterações no código que usa o campo união. Alterar o código para um valor alteraria os dados armazenados na união, o que afeta outros campos, uma vez que os campos em tipos de união compartilham a mesma memória. Dependendo do tamanho do valor, também pode alterar o tamanho da união.
Os sindicatos anónimos estão agora mais conformes com a norma. Versões anteriores do compilador geraram um construtor explícito e um destruidor para uniões anônimas. Essas funções geradas pelo compilador são excluídas no Visual Studio 2015.
struct S { S(); }; union { struct { S s; }; } u; // C2280O código anterior gera o seguinte erro no Visual Studio 2015:
error C2280: '<unnamed-type-u>::<unnamed-type-u>(void)': attempting to reference a deleted function note: compiler has generated '<unnamed-type-u>::<unnamed-type-u>' herePara resolver esse problema, forneça suas próprias definições do construtor e/ou destruidor.
struct S { // Provide a default constructor by adding an empty function body. S() {} }; union { struct { S s; }; } u;Sindicatos com estruturas anónimas
A fim de estar em conformidade com o padrão, o comportamento em tempo de execução mudou para membros de estruturas anônimas em uniões. O construtor para membros anônimos da estrutura em um sindicato não é mais implicitamente chamado quando tal união é criada. Além disso, o destrutor para membros anónimos da estrutura numa união não é mais implicitamente chamado quando a união sai do escopo. Considere o código a seguir, no qual uma união U contém uma estrutura anônima que contém uma estrutura de membro nomeada S que tem um destruidor.
#include <stdio.h> struct S { S() { printf("Creating S\n"); } ~S() { printf("Destroying S\n"); } }; union U { struct { S s; }; U() {} ~U() {} }; void f() { U u; // Destructor implicitly called here. } int main() { f(); char s[1024]; printf("Press any key.\n"); gets_s(s); return 0; }No Visual Studio 2013, o construtor para S é chamado quando a união é criada, e o destruidor para S é chamado quando a pilha para a função f é limpa. Mas no Visual Studio 2015, o construtor e o destruidor não são chamados. O compilador dá um aviso sobre essa mudança de comportamento.
warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly calledPara restaurar o comportamento original, dê um nome à estrutura anônima. O comportamento de tempo de execução de estruturas não anônimas é o mesmo, independentemente da versão do compilador.
#include <stdio.h> struct S { S() { printf("Creating S.\n"); } ~S() { printf("Destroying S\n"); } }; union U { struct { S s; } namedStruct; U() {} ~U() {} }; void f() { U u; } int main() { f(); char s[1024]; printf("Press any key.\n"); gets_s(s); return 0; }Como alternativa, tente mover o código do construtor e do destruidor para novas funções e adicione chamadas a essas funções do construtor e do destruidor para a união.
#include <stdio.h> struct S { void Create() { printf("Creating S.\n"); } void Destroy() { printf("Destroying S\n"); } }; union U { struct { S s; }; U() { s.Create(); } ~U() { s.Destroy(); } }; void f() { U u; } int main() { f(); char s[1024]; printf("Press any key.\n"); gets_s(s); return 0; }Resolução do modelo
Alterações foram realizadas na resolução de nomes para modelos. Em C++, ao considerar candidatos para a resolução de um nome, pode acontecer que um ou mais nomes em consideração como potenciais correspondências resultem numa instanciação inválida de template. Essas instanciações inválidas normalmente não causam erros do compilador, um princípio conhecido como SFINAE (Substitution Failure Is Not An Error).
Agora, se o SFINAE exigir que o compilador instancie a especialização de um modelo de classe, então quaisquer erros que ocorram durante esse processo são erros do compilador. Em versões anteriores, o compilador ignorava tais erros. Por exemplo, considere o seguinte código:
#include <type_traits> template< typename T> struct S { S() = default; S(const S&); S(S& &); template< typename U, typename = typename std::enable_if< std::is_base_of< T, U> ::value> ::type> S(S< U> & &); }; struct D; void f1() { S< D> s1; S< D> s2(s1); } struct B { }; struct D : public B { }; void f2() { S< D> s1; S< D> s2(s1); }Se você compilar com o compilador atual, você receberá o seguinte erro:
type_traits(1110): error C2139: 'D': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_base_of' ..\t331.cpp(14): note: see declaration of 'D' ..\t331.cpp(10): note: see reference to class template instantiation 'std::is_base_of<T,U>' being compiled with [ T=D, U=D ]Isso ocorre porque no momento da primeira invocação do is_base_of a classe
Dainda não foi definida.Neste caso, a correção é não usar tais características de tipo até que a classe tenha sido definida. Se você mover as definições de
BeDpara o início do arquivo de código, o erro será resolvido. Se as definições estiverem em arquivos de cabeçalho, verifique a ordem das instruções include para os arquivos de cabeçalho para garantir que todas as definições de classe sejam compiladas antes que os modelos problemáticos sejam usados.Construtores de cópia
No Visual Studio 2013 e no Visual Studio 2015, o compilador gera um construtor de cópia para uma classe se essa classe tiver um construtor de movimento definido pelo utilizador, mas não tiver um construtor de cópia definido pelo utilizador. No Dev14, esse construtor de cópia gerado implicitamente também está marcado como "= delete".
main declarado com 'extern "C"' passa a requerer um tipo de retorno.
O código a seguir agora produz C4430.
extern "C" __cdecl main(){} // C4430Para corrigir o erro, adicione o tipo de retorno:
extern "C" int __cdecl main(){} // OKtypename não é permitido num inicializador de membro
O código a seguir agora produz C2059:
template<typename T> struct S1 : public T::type { S1() : typename T::type() // C2059 { } }; struct S2 { typedef S2 type; }; S1<S2> s;Para corrigir o erro, remova
typenamedo inicializador:S1() : T::type() // OK ...A classe de armazenamento nas especializações explícitas é ignorada.
No código a seguir, o especificador de classe de armazenamento estático é ignorado
template <typename T> void myfunc(T h) { } template<> static void myfunc(double h) // static is ignored { }Uma constante usada em um static_assert dentro de um modelo de classe sempre falhará.
O código a seguir faz com que o
static_assertsempre falhe:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations herePara contornar esse problema, envolva o valor em um
struct:template <size_t some_value> struct constant_false { static const bool value = false; }; template <size_t some_value> struct S1 { static_assert(constant_false<some_value>::value, "default not valid"); }; //other partial specializations hereRegras impostas para as declarações antecipadas. (Aplica-se apenas a C.)
O código a seguir agora produz C2065:
struct token_s; typedef int BOOL; typedef int INT; typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifierPara corrigir esse problema, adicione as declarações de encaminhamento adequadas:
struct token_s; typedef int BOOL; typedef int INT; // forward declarations: typedef struct token_s TOKEN; typedef TOKEN *PTOKEN; typedef int(*PFNTERM)(PTOKEN, BOOL, INT);Aplicação mais consistente de tipos de ponteiro de função
O código a seguir agora produz C2197:
typedef int(*F1)(int); typedef int(*F2)(int, int); void func(F1 f, int v1, int v2) { f(v1, v2); // C2197 }Chamadas ambíguas para funções sobrecarregadas
O código a seguir agora produz C266: 'N::bind': chamada ambígua para função sobrecarregada
template<typename R, typename T, typename T1, typename A1> void bind(R(T::*)(T1), A1&&); namespace N { template <typename T, typename R, typename ... Tx> void bind(R(T::*)(Tx...), T* ptr); } using namespace N; class Manager { public: void func(bool initializing); void mf() { bind(&Manager::func, this); //C2668 } };Para corrigir o erro, você pode qualificar totalmente a chamada para
bind: N::bind(...). No entanto, se esta alteração for manifesta através de um identificador não declarado (C2065), poderá ser adequado corrigi-la com umausingdeclaração.Esse padrão acontece frequentemente com ComPtr e outros tipos no
Microsoft::WRLnamespace.Corrigir endereço incorreto de
O código a seguir agora gera o erro C2440: '=': impossível converter de 'type *' para 'type'. Para corrigir o erro, altere &(type) para (type) e (&f()) para (f()).
// C typedef void (*type)(void); void f(int i, type p); void g(int); void h(void) { f(0, &(type)g); } // C++ typedef void(*type)(void); type f(); void g(type); void h() { g(&f()); }String literal é uma matriz constante
O código a seguir produz agora C2664: 'void f(void )': não é possível converter o argumento 1 de 'const char ()[2]' para 'void *'
void f(void *); void h(void) { f(&__FUNCTION__); void *p = &""; }Para corrigir o erro, altere o tipo de parâmetro de função para
const void*, ou altere o corpo dehpara se parecer com este exemplo:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }Cadeias de caracteres UDL C++11
O código a seguir agora produz o erro C3688: sufixo literal inválido 'L'; operador literal ou modelo de operador literal 'operador ""L' não encontrado
#define MACRO #define STRCAT(x, y) x\#\#y int main(){ auto *val1 = L"string"MACRO; auto *val2 = L"hello "L"world"; std::cout << STRCAT(L"hi ", L"there"); }Para corrigir o erro, altere o código para adicionar um espaço:
#define MACRO // Remove ##. Strings are automatically // concatenated so they aren't needed #define STRCAT(x, y) x y int main(){ //Add space after closing quote auto *val1 = L"string" MACRO; auto *val2 = L"hello " L"world"; std::cout << STRCAT(L"hi ", L"there"); }No exemplo acima,
MACROnão é mais analisado como dois tokens (uma cadeia de caracteres seguida por uma macro). Agora ele é analisado como um único token UDL. O mesmo se aplica a L""L"", que foi analisado anteriormente como L"" e L"", e agora é analisado como L""L e "".As regras de concatenação de cordas também foram colocadas em conformidade com o padrão, o que significa que L"a" "b" é equivalente a L"ab". As edições anteriores do Visual Studio não aceitavam concatenação de cadeias de caracteres com largura de caracteres diferente.
Caractere vazio C++11 removido
O código a seguir agora produz o erro C2137: constante de caractere vazio
bool check(wchar_t c){ return c == L''; //implicit null character }Para corrigir o erro, altere o código para tornar o nulo explícito:
bool check(wchar_t c){ return c == L'\0'; }As exceções MFC não podem ser capturadas pelo valor porque não podem ser copiadas
O seguinte código em uma aplicação MFC agora causa o erro C2316: 'D': não pode ser capturada, pois o destrutor e/ou o construtor de cópia são inacessíveis ou foram excluídos.
struct B { public: B(); private: B(const B &); }; struct D : public B { }; int main() { try { } catch (D) // C2316 { } }Para corrigir o código, você pode alterar o bloco catch para
catch (const D &), mas a melhor solução geralmente é usar as macros MFC TRY/CATCH.alignofagora é uma palavra-chaveO código a seguir agora produz o erro C2332: 'class': nome da tag ausente. Para corrigir o código você deve renomear a classe ou, se a classe estiver executando o mesmo trabalho que
alignof, basta substituir a classe com a nova palavra-chave.class alignof{}constexpragora é uma palavra-chaveO código a seguir agora produz o erro C2059: erro de sintaxe: ')'. Para corrigir o código, deve renomear qualquer nome de função ou variável que seja chamado de
constexpr.int constexpr() {return 1;}Tipos móveis não podem ser const
Quando uma função retorna um tipo que se destina a ser movido, seu tipo de retorno não deve ser
const.Construtores de cópia eliminados
O código a seguir agora produz C2280 'S::S(S &&)': tentando fazer referência a uma função eliminada.
struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = S(2, 3); //C2280Para corrigir o erro, use a inicialização direta para
S2:struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = {2,3}; //OKA conversão em ponteiro de função só é gerada quando não há captura lambda
O código a seguir produz C2664 no Visual Studio 2015.
void func(int(*)(int)) {} int main() { func([=](int val) { return val; }); }Para corrigir o erro, remova o
=da lista de captura.Chamadas ambíguas que envolvem operadores de conversão
O código a seguir agora produz o erro C2440: 'type cast': não é possível converter de 'S2' para 'S1':
struct S1 { S1(int); }; struct S2 { operator S1(); operator int(); }; void f(S2 s2) { (S1)s2; }Para corrigir o erro, chame explicitamente o operador de conversão:
void f(S2 s2) { //Explicitly call the conversion operator s2.operator S1(); // Or S1((int)s2); }O código a seguir agora produz o erro C2593: 'operator =' é ambíguo:
struct S1 {}; struct S2 { operator S1&(); operator S1() const; }; void f(S1 *p, S2 s) { *p = s; }Para corrigir o erro, chame explicitamente o operador de conversão:
void f(S1 *p, S2 s) { *p = s.operator S1&(); }Corrigir cópia inválida durante a inicialização de membros de dados não estáticos (NSDMI)
O código a seguir agora produz o erro C2664: 'S1::S1(S1 &&)': não é possível converter o argumento 1 de 'bool' para 'const S1 &':
struct S1 { explicit S1(bool); }; struct S2 { S1 s2 = true; // error };Para corrigir o erro, use a inicialização direta:
struct S2 { S1 s1{true}; // OK };Acessando construtores dentro de instruções decltype
O código a seguir agora produz C2248: 'S::S': não é possível acessar o membro privado declarado na classe 'S':
class S { S(); public: int i; }; class S2 { auto f() -> decltype(S().i); };Para corrigir o erro, adicione uma declaração de amigo para
S2emS:class S { S(); friend class S2; // Make S2 a friend public: int i; };O ctor padrão do lambda é implicitamente excluído
O código a seguir agora produz o erro C3497: Não é possível construir uma instância de um lambda:
void func(){ auto lambda = [](){}; decltype(lambda) other; }Para corrigir o erro, remova a necessidade do construtor padrão ser chamado. Se o lambda não capturar nada, pode ser convertido num ponteiro de função.
Lambdas com um operador de atribuição excluído
O código a seguir agora produz o erro C2280:
#include <memory> #include <type_traits> template <typename T, typename D> std::unique_ptr<T, typename std::remove_reference<D &&>::type> wrap_unique(T *p, D &&d); void f(int i) { auto encodedMsg = wrap_unique<unsigned char>(nullptr, [i](unsigned char *p) { }); encodedMsg = std::move(encodedMsg); }Para corrigir o erro, substitua o lambda por uma classe functor ou remova a necessidade de usar o operador de atribuição.
Tentando mover um objeto com o construtor de cópia excluído
O código a seguir agora produz o erro C2280: 'moveable::moveable(const moveable &)': tentando fazer referência a uma função excluída
struct moveable { moveable() = default; moveable(moveable&&) = default; moveable(const moveable&) = delete; }; struct S { S(moveable && m) : m_m(m)//copy constructor deleted {} moveable m_m; };Para corrigir o erro, use
std::moveem vez disso:S(moveable && m) : m_m(std::move(m))A classe local não pode fazer referência a outra classe local definida posteriormente na mesma função
O código a seguir agora produz o erro C2079: 's' usa uma struct não definida 'main::S2'
int main() { struct S2; struct S1 { void f() { S2 s; } }; struct S2 {}; }Para corrigir o erro, mova para cima a definição de
S2:int main() { struct S2 { //moved up }; struct S1 { void f() { S2 s; } }; }Não é possível chamar um ctor de base protegida no corpo do ctor derivado.
O código a seguir agora produz o erro C2248: 'S1::S1': não é possível acessar o membro protegido declarado na classe 'S1'
struct S1 { protected: S1(); }; struct S2 : public S1 { S2() { S1(); } };Para corrigir o erro, remova a chamada para
S2do construtor emS1()e, se necessário, coloque-a em outra função.{} impede a conversão em ponteiro
O código a seguir agora produz C2439 'S::p': membro não pôde ser inicializado
struct S { S() : p({ 0 }) {} void *p; };Para corrigir o erro, remova as chaves que envolvem o
0ou use onullptrno seu lugar, conforme ilustrado neste exemplo:struct S { S() : p(nullptr) {} void *p; };Definição de macro incorreta e uso entre parênteses
O exemplo seguinte agora resulta no erro C2008: ';': inesperado na definição de macro
#define A; //cause of error struct S { A(); // error };Para corrigir o problema, altere a linha superior para
#define A();O código a seguir produz o erro C2059: erro de sintaxe: ')'
//notice the space after 'A' #define A () ; struct S { A(); };Para corrigir o código, remova o espaço entre A e ().
O código a seguir produz o erro C2091: função retorna função.
#define DECLARE void f() struct S { DECLARE(); };Para corrigir o erro, remova os parênteses após DECLARE em S:
DECLARE;.O seguinte código produz o erro C2062: tipo 'int' inesperado
#define A (int) struct S { A a; };Para corrigir o problema, defina
Aassim:#define A intParêntesis adicionais nas declarações
O seguinte código produz o erro C2062: tipo 'int' inesperado
struct S { int i; (int)j; };Para corrigir o erro, remova os parênteses ao redor do
j. Se os parênteses forem necessários para clareza, use umtypedef.Construtores gerados pelo compilador e __declspec(novtable)
No Visual Studio 2015, há uma maior probabilidade de que construtores inline gerados pelo compilador de classes abstratas com classes base virtuais possam expor o uso inadequado de
__declspec(novtable)quando usados em combinação com__declspec(dllimport).auto requer uma única expressão na inicialização de lista direta
O código a seguir agora produz o erro C3518: 'testPositions': em um contexto de inicialização de lista direta, o tipo para 'auto' só pode ser deduzido de uma única expressão inicializadora
auto testPositions{ std::tuple<int, int>{13, 33}, std::tuple<int, int>{-23, -48}, std::tuple<int, int>{38, -12}, std::tuple<int, int>{-21, 17} };Para corrigir o erro, uma possibilidade é inicializar
testPositionsda seguinte forma:std::tuple<int, int> testPositions[]{ std::tuple<int, int>{13, 33}, std::tuple<int, int>{-23, -48}, std::tuple<int, int>{38, -12}, std::tuple<int, int>{-21, 17} };Verificação de tipos vs. ponteiros para tipos para is_convertible
O código a seguir agora faz com que a asserção estática falhe.
struct B1 { private: B1(const B1 &); }; struct B2 : public B1 {}; struct D : public B2 {}; static_assert(std::is_convertible<D, B2>::value, "fail");Para corrigir o erro, altere o
static_assertpara que ele compare ponteiros comDeB2:static_assert(std::is_convertible<D*, B2*>::value, "fail");__declspec(novtable) declarações devem ser coerentes
__declspecAs declarações devem ser consistentes em todas as bibliotecas. O código a seguir agora produzirá uma violação de regra de uma definição (ODR)://a.cpp class __declspec(dllexport) A { public: A(); A(const A&); virtual ~A(); private: int i; }; A::A() {} A::~A() {} A::A(const A&) {} //b.cpp // compile with cl.exe /nologo /LD /EHsc /Osx b.cpp #pragma comment(lib, "A") class __declspec(dllimport) A { public: A(); A(const A&); virtual ~A(); private: int i; }; struct __declspec(novtable) __declspec(dllexport) B : virtual public A { virtual void f() = 0; }; //c.cpp #pragma comment(lib, "A") #pragma comment(lib, "B") class __declspec(dllimport) A { public: A(); A(const A&); virtual ~A(); private: int i; }; struct /* __declspec(novtable) */ __declspec(dllimport) B // Error. B needs to be novtable here also. : virtual public A { virtual void f() = 0; }; struct C : virtual B { virtual void f(); }; void C::f() {} C c;
Melhorias de conformidade na Atualização 1
Classes base virtuais privadas e herança indireta
Versões anteriores do compilador permitiam que uma classe derivada chamasse funções membro das suas classes base derivadas indiretamente. Esse comportamento antigo estava incorreto e não está em conformidade com o padrão C++. O compilador não aceita mais o código escrito dessa maneira e emite o erro do compilador C2280 como resultado.
error C2280: 'void *S3::__delDtor(unsigned int)': attempting to reference a deleted functionExemplo (antes)
class base { protected: base(); ~base(); }; class middle : private virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; // }Exemplo (depois)
class base; // as above class middle : protected virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; }- ou -
class base; // as above class middle : private virtual base {}; class top : public virtual middle, private virtual bottom {}; void destroy(top *p) { delete p; }Operador sobrecarregado novo e operador excluído
As versões anteriores do compilador permitiam que o operador não-membro new e o non-member operator delete fossem declarados estáticos e declarados em namespaces diferentes do namespace global. Esse comportamento antigo criava um risco de que o programa não chamasse a implementação do operador
newoudeleteque o programador pretendia, resultando silenciosamente em um mau comportamento em tempo de execução. O compilador não aceita mais o código escrito dessa maneira e emite o erro do compilador C2323.error C2323: 'operator new': non-member operator new or delete functions may not be declared static or in a namespace other than the global namespace.Exemplo (antes)
static inline void * __cdecl operator new(size_t cb, const std::nothrow_t&) // error C2323Exemplo (depois)
void * __cdecl operator new(size_t cb, const std::nothrow_t&) // removed 'static inline'Além disso, embora o compilador não forneça um diagnóstico específico, o operador
newem linha é considerado mal formado.Chamando 'operador tipo()' (conversão definida pelo usuário) em tipos que não são de classe
As versões anteriores do compilador permitiam que 'operator type()' fosse chamado em tipos não-classe, ignorando-o silenciosamente. Esse comportamento antigo criava um risco de geração silenciosa de código ruim, resultando em comportamento de tempo de execução imprevisível. O compilador não aceita mais o código escrito dessa maneira e emite o erro do compilador C2228.
error C2228: left of '.operator type' must have class/struct/unionExemplo (antes)
typedef int index_t; void bounds_check(index_t index); void login(int column) { bounds_check(column.operator index_t()); // error C2228 }Exemplo (depois)
typedef int index_t; void bounds_check(index_t index); void login(int column) { bounds_check(column); // removed cast to 'index_t', 'index_t' is an alias of 'int' }Nome de tipo redundante em especificadores de tipo elaborados
Versões anteriores do compilador permitiram
typenamenum especificador de tipo elaborado, mas o código escrito dessa maneira é semanticamente incorreto. O compilador não aceita mais o código escrito dessa maneira e emite o erro do compilador C3406.error C3406: 'typename' cannot be used in an elaborated type specifierExemplo (antes)
template <typename class T> class container;Exemplo (depois)
template <class T> // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case class container;Dedução de tipo de matrizes de uma lista de inicializadores
As versões anteriores do compilador não suportavam a dedução de tipo de matrizes de uma lista de inicializadores. O compilador agora suporta essa forma de dedução de tipo e, como resultado, chamadas para modelos de função usando listas de inicializadores podem agora ser ambíguas ou uma sobrecarga diferente pode ser escolhida do que em versões anteriores do compilador. Para resolver esses problemas, o programa deve agora especificar explicitamente a sobrecarga que o programador pretendia.
Quando esse novo comportamento faz com que a resolução de sobrecarga considere um candidato adicional que seja tão bom quanto o candidato histórico, a chamada se torna ambígua e o compilador emite o erro de compilador C2668 como resultado.
error C2668: 'function' : ambiguous call to overloaded function.Exemplo 1: Chamada ambígua para função sobrecarregada (antes)
// In previous versions of the compiler, code written in this way would unambiguously call f(int, Args...) template < typename... Args> void f(int, Args...); // template < int N, typename... Args> void f(const int(&)[N], Args...); int main() { // The compiler now considers this call ambiguous, and issues a compiler error f({ 3 }); error C2668 : 'f' ambiguous call to overloaded function }Exemplo 1: chamada ambígua para função sobrecarregada (depois)
template < typename... Args> void f(int, Args...); // template < int N, typename... Args> void f(const int(&)[N], Args...); int main() { // To call f(int, Args...) when there is just one expression in the initializer list, remove the braces from it. f(3); }Quando esse novo comportamento faz com que a resolução de sobrecarga considere um candidato adicional que seja melhor do que o candidato histórico, a chamada resolve inequivocamente para o novo candidato, causando uma mudança no comportamento do programa que provavelmente é diferente do que o programador pretendia.
Exemplo 2: alteração na resolução de sobrecarga (antes)
// In previous versions of the compiler, code written in this way would unambiguously call f(S, Args...) struct S { int i; int j; }; template < typename... Args> void f(S, Args...); template < int N, typename... Args> void f(const int *&)[N], Args...); int main() { // The compiler now resolves this call to f(const int (&)[N], Args...) instead f({ 1, 2 }); }Exemplo 2: alteração na resolução de sobrecarga (após)
struct S; // as before template < typename... Args> void f(S, Args...); template < int N, typename... Args> void f(const int *&)[N], Args...); int main() { // To call f(S, Args...), perform an explicit cast to S on the initializer list. f(S{ 1, 2 }); }Restauração dos avisos de instrução do interruptor
Uma versão anterior do compilador removeu alguns avisos relacionados a
switchinstruções, esses avisos agora foram restaurados. O compilador agora emite os avisos restaurados, e os avisos relacionados a casos específicos (incluindo o caso padrão) agora são emitidos na linha que contém o caso ofensivo, em vez de na última linha da instrução switch. Como resultado de emitir agora esses avisos em linhas diferentes das anteriores, os avisos anteriormente suprimidos pelo uso de#pragma warning(disable:####)podem já não ser suprimidos como se pretendia. Para suprimir estas advertências como pretendido, poderá ser necessário deslocar a diretiva#pragma warning(disable:####)para uma linha acima do primeiro caso infrator. A seguir estão os avisos restaurados:warning C4060: switch statement contains no 'case' or 'default' labelswarning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case labelwarning C4062: enumerator 'bit1' in switch of enum 'flags' is not handledwarning C4063: case 'bit32' is not a valid value for switch of enum 'flags'warning C4064: switch of incomplete enum 'flags'warning C4065: switch statement contains 'default' but no 'case' labelswarning C4808: case 'value' is not a valid value for switch condition of type 'bool'Warning C4809: switch statement has redundant 'default' label; all possible 'case' labels are givenExemplo de C4063 (antes)
class settings { public: enum flags { bit0 = 0x1, bit1 = 0x2, ... }; ... }; int main() { auto val = settings::bit1; switch (val) { case settings::bit0: break; case settings::bit1: break; case settings::bit0 | settings::bit1: // warning C4063 break; } }Exemplo de C4063 (após)
class settings { ... }; // as above int main() { // since C++11, use std::underlying_type to determine the underlying type of an enum typedef std::underlying_type< settings::flags> ::type flags_t; auto val = settings::bit1; switch (static_cast< flags_t> (val)) { case settings::bit0: break; case settings::bit1: break; case settings::bit0 | settings::bit1: // ok break; } };Exemplos de outros avisos restaurados são fornecidos em sua documentação.
#include: uso do especificador de diretório pai '..' em nome do caminho (afeta apenas
/Wall/WX)As versões anteriores do compilador não detetavam o uso do especificador de diretório pai '..' no nome do caminho das
#includediretivas. O código escrito dessa maneira geralmente se destina a incluir cabeçalhos que existem fora do projeto usando incorretamente caminhos relativos ao projeto. Esse comportamento antigo criava um risco de que o programa pudesse ser compilado incluindo um arquivo de origem diferente do que o programador pretendia, ou que esses caminhos relativos não seriam portáteis para outros ambientes de compilação. O compilador agora deteta e notifica o programador de código escrito desta forma e emite um aviso opcional do compilador C4464, se ativado.warning C4464: relative include path contains '..'Exemplo (antes)
#include "..\headers\C4426.h" // emits warning C4464Exemplo (depois)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directoriesAlém disso, embora o compilador não forneça um diagnóstico específico, também recomendamos que o especificador de diretório pai ".." não seja usado para especificar os diretórios de inclusão do seu projeto.
#pragma optimize() estende-se além do final do ficheiro de cabeçalho (apenas afeta
/Wall/WX)As versões anteriores do compilador não detetaram alterações nas configurações do sinalizador de otimização que escapam de um arquivo de cabeçalho incluído em uma unidade de tradução. O compilador agora deteta e notifica o programador do código escrito desta forma e emite um aviso opcional do compilador C4426 no local da infração
#include, se ativado. Esse aviso só é emitido se as alterações entrarem em conflito com os sinalizadores de otimização definidos por argumentos de linha de comando para o compilador.warning C4426: optimization flags changed after including header, may be due to #pragma optimize()Exemplo (antes)
// C4426.h #pragma optimize("g", off) ... // C4426.h ends // C4426.cpp #include "C4426.h" // warning C4426Exemplo (depois)
// C4426.h #pragma optimize("g", off) ... #pragma optimize("", on) // restores optimization flags set via command-line arguments // C4426.h ends // C4426.cpp #include "C4426.h"Incompatibilidade de #pragma warning(push) e #pragma warning(pop) (afeta apenas
/Wall/WX)As versões anteriores do compilador não detetavam alterações de estado
#pragma warning(push)sendo emparelhadas com alterações de estado#pragma warning(pop)num ficheiro de origem diferente, o que raramente é pretendido. Esse comportamento antigo criava um risco de que o programa fosse compilado com um conjunto diferente de avisos habilitados do que o programador pretendia, possivelmente resultando em um mau comportamento silencioso de tempo de execução. O compilador agora deteta e notifica o programador sobre o código escrito dessa forma e emite um aviso opcional do compilador C5031 na localização da correspondência#pragma warning(pop), se ativado. Este aviso inclui uma nota que faz referência à localização do correspondente #pragma warning(push).warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different fileExemplo (antes)
// C5031_part1.h #pragma warning(push) #pragma warning(disable:####) ... // C5031_part1.h ends without #pragma warning(pop) // C5031_part2.h ... #pragma warning(pop) // pops a warning state not pushed in this source file ... // C5031_part1.h ends // C5031.cpp #include "C5031_part1.h" // leaves #pragma warning(push) 'dangling' ... #include "C5031_part2.h" // matches 'dangling' #pragma warning(push), resulting in warning C5031 ...Exemplo (depois)
// C5031_part1.h #pragma warning(push) #pragma warning(disable:####) ... #pragma warning(pop) // pops the warning state pushed in this source file // C5031_part1.h ends without #pragma warning(pop) // C5031_part2.h #pragma warning(push) // pushes the warning state pushed in this source file #pragma warning(disable:####) ... #pragma warning(pop) // C5031_part1.h ends // C5031.cpp #include "C5031_part1.h" // #pragma warning state changes are self-contained and independent of other source files or their #include order. ... #include "C5031_part2.h" ...Embora incomum, o código escrito dessa maneira às vezes é intencional. O código escrito desta forma é sensível a alterações na
#includeordem, sempre que possível, recomendamos que os arquivos de código-fonte gerenciem o estado de aviso de forma independente.Aviso de #pragma incomparável (push) (afeta
/Wall/WXapenas )As versões anteriores do compilador não detetavam alterações de estado não correspondentes no final de uma unidade de tradução. O compilador agora deteta e notifica o programador de código escrito desta forma, e emite um aviso opcional do compilador C5032 no local do elemento
#pragma warning(push)não correspondido, caso esteja ativado. Este aviso só é emitido se não houver erros de compilação na unidade de tradução.warning C5032: detected #pragma warning(push) with no corresponding #pragma warning(pop)Exemplo (antes)
// C5032.h #pragma warning(push) #pragma warning(disable:####) ... // C5032.h ends without #pragma warning(pop) // C5032.cpp #include "C5032.h" ... // C5032.cpp ends -- the translation unit is completed without #pragma warning(pop), resulting in warning C5032 on line 1 of C5032.hExemplo (depois)
// C5032.h #pragma warning(push) #pragma warning(disable:####) ... #pragma warning(pop) // matches #pragma warning (push) on line 1 // C5032.h ends // C5032.cpp #include "C5032.h" ... // C5032.cpp ends -- the translation unit is completed without unmatched #pragma warning(push)Avisos adicionais podem ser emitidos como resultado de um melhor rastreamento do estado de aviso #pragma
As versões anteriores do compilador não rastreavam suficientemente bem as alterações de estado de aviso do #pragma para emitir todos os avisos pretendidos. Esse comportamento criou um risco de que certos avisos seriam efetivamente suprimidos em circunstâncias diferentes do que o programador pretendia. O compilador agora rastreia
#pragma warningo estado de forma mais robusta - especialmente relacionada a#pragma warningmudanças de estado dentro dos modelos - e, opcionalmente, emite novos avisos C5031 e C5032, que se destinam a ajudar o programador a localizar usos não intencionais de#pragma warning(push)e#pragma warning(pop).Como resultado de um melhor
#pragma warningcontrole de alterações de estado, avisos anteriormente suprimidos incorretamente ou avisos relacionados a problemas anteriormente diagnosticados incorretamente podem agora ser emitidos.Melhor identificação de código inacessível
As alterações na biblioteca padrão do C++ e a capacidade aprimorada de inserir chamadas de função em relação às versões anteriores do compilador podem permitir que o compilador prove que determinado código agora está inacessível. Esse novo comportamento pode resultar em novas instâncias de avisos C4720 emitidas com mais frequência.
warning C4720: unreachable codeEm muitos casos, esse aviso só pode ser emitido ao compilar com otimizações habilitadas, uma vez que as otimizações podem inserir mais chamadas de função, eliminar código redundante ou tornar possível determinar que determinado código está inacessível. Observamos que novos casos de aviso C4720 têm ocorrido com frequência em blocos try/catch , especialmente em relação ao uso de std::find.
Exemplo (antes)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // ok }Exemplo (depois)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // warning C4702: unreachable code }
Melhorias de conformidade na Atualização 2
Avisos e erros adicionais podem ser emitidos como resultado do suporte parcial para a expressão SFINAE
As versões anteriores do compilador não analisavam certos tipos de expressões dentro
decltypede especificadores devido à falta de suporte para a expressão SFINAE. Esse comportamento antigo estava incorreto e não está em conformidade com o padrão C++. O compilador agora analisa essas expressões e tem suporte parcial para a expressão SFINAE devido a melhorias contínuas de conformidade. Como resultado, o compilador agora emite avisos e erros encontrados em expressões que as versões anteriores do compilador não analisavam.Quando esse novo comportamento analisa uma
decltypeexpressão que inclui um tipo que ainda não foi declarado, o compilador emite o erro de compilador C2039 como resultado.error C2039: 'type': is not a member of 'global namespace'Exemplo 1: utilização de um tipo não declarado (antes)
struct s1 { template < typename T> auto f() - > decltype(s2< T> ::type::f()); // error C2039 template< typename> struct s2 {}; }Exemplo 1 (depois)
struct s1 { template < typename> // forward declare s2struct s2; template < typename T> auto f() - > decltype(s2< T> ::type::f()); template< typename> struct s2 {}; }Quando esse novo comportamento analisa uma expressão
decltypeque está faltando um uso necessário da palavra-chavetypenamepara especificar que um nome dependente é um tipo, o compilador emite o aviso do compilador C4346 juntamente com o erro do compilador C2923.warning C4346: 'S2<T>::Type': dependent name is not a typeerror C2923: 's1': 'S2<T>::Type' is not a valid template type argument for parameter 'T'Exemplo 2: nome dependente não é um tipo (antes)
template < typename T> struct s1 { typedef T type; }; template < typename T> struct s2 { typedef T type; }; template < typename T> T declval(); struct s { template < typename T> auto f(T t) - > decltype(t(declval< S1< S2< T> ::type> ::type> ())); // warning C4346, error C2923 };Exemplo 2 (após)
template < typename T> struct s1 { ... }; // as above template < typename T> struct s2 { ... }; // as above template < typename T> T declval(); struct s { template < typename T> auto f(T t) - > decltype(t(declval< S1< typename S2< T> ::type> ::type> ())); };volatileAs variáveis de membro impedem construtores e operadores de atribuição definidos implicitamenteAs versões anteriores do compilador permitiam que uma classe que tem
volatilevariáveis membro tivesse construtores de cópia/movimentação padrão e operadores de atribuição de cópia/movimentação padrão gerados automaticamente. Esse comportamento antigo estava incorreto e não está em conformidade com o padrão C++. O compilador agora considera uma classe que temvolatilevariáveis membro para ter operadores de construção e atribuição não triviais, o que impede que implementações padrão desses operadores sejam geradas automaticamente. Quando tal classe é um membro de uma união (ou uma união anônima dentro de uma classe), os construtores copy/move e operadores de atribuição copy/move da união (ou a classe que contém a união anônima) serão implicitamente definidos como excluídos. Tentar construir ou copiar a união (ou classe que contém a união anônima) sem defini-los explicitamente é um erro e o compilador emite o erro do compilador C2280 como resultado.error C2280: 'B::B(const B &)': attempting to reference a deleted functionExemplo (antes)
struct A { volatile int i; volatile int j; }; extern A* pa; struct B { union { A a; int i; }; }; B b1{ *pa }; B b2(b1); // error C2280Exemplo (depois)
struct A { int i; int j; }; extern volatile A* pa; A getA() // returns an A instance copied from contents of pa { A a; a.i = pa - > i; a.j = pa - > j; return a; } struct B; // as above B b1{ GetA() }; B b2(b1); // error C2280As funções de membro estático não suportam qualificadores cv.
As versões anteriores do Visual Studio 2015 permitiam que as funções de membro estático pudessem ter qualificadores cv ("cv-qualifiers"). Esse comportamento é devido a uma regressão no Visual Studio 2015 e Visual Studio 2015 Atualização 1; O Visual Studio 2013 e versões anteriores do compilador rejeitam código escrito dessa maneira. O comportamento do Visual Studio 2015 e Visual Studio 2015 Atualização 1 está incorreto e não está em conformidade com o padrão C++. O Visual Studio 2015 Update 2 rejeita o código escrito dessa maneira e emite o erro de compilador C2511.
error C2511: 'void A::func(void) const': overloaded member function not found in 'A'Exemplo (antes)
struct A { static void func(); }; void A::func() const {} // C2511Exemplo (depois)
struct A { static void func(); }; void A::func() {} // removed constDeclaração antecipada de enum não é permitida no código WinRT (afeta apenas
/ZW)O código compilado para o Tempo de Execução do Windows (WinRT) não permite que
enumos tipos sejam declarados antecipadamente, da mesma forma que quando o código C++ gerido é compilado para o .Net Framework usando a opção de compilador/clr. Esse comportamento garante que o tamanho de uma enumeração é sempre conhecido e pode ser projetado corretamente para o sistema de tipo WinRT. O compilador rejeita o código escrito desta forma e emite o erro do compilador C2599 juntamente com o erro do compilador C3197.error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowederror C3197: 'public': can only be used in definitionsExemplo (antes)
namespace A { public enum class CustomEnum : int32; // forward declaration; error C2599, error C3197 } namespace A { public enum class CustomEnum : int32 { Value1 }; } public ref class Component sealed { public: CustomEnum f() { return CustomEnum::Value1; } };Exemplo (depois)
// forward declaration of CustomEnum removed namespace A { public enum class CustomEnum : int32 { Value1 }; } public ref class Component sealed { public: CustomEnum f() { return CustomEnum::Value1; } };O operador não-membro sobrecarregado novo e o operador excluído não podem ser declarados em linha (Nível 1 (
/W1) on-by-default)As versões anteriores do compilador não emitem um aviso quando as funções new e operator delete do operador não-membro são declaradas em linha. O código escrito desta forma é mal formado (não é necessário diagnóstico) e pode causar problemas de memória resultantes de operadores new e delete incompatíveis (especialmente quando usados em conjunto com deslocamento dimensionado) que podem ser difíceis de detetar. O compilador agora emite o aviso do compilador C4595 para ajudar a identificar o código escrito dessa maneira.
warning C4595: 'operator new': non-member operator new or delete functions may not be declared inlineExemplo (antes)
inline void* operator new(size_t sz) // warning C4595 { ... }Exemplo (depois)
void* operator new(size_t sz) // removed inline { ... }A correção do código escrito dessa maneira pode exigir que as definições do operador sejam movidas de um arquivo de cabeçalho para um arquivo de origem correspondente.
Melhorias de conformidade na Atualização 3
std::is_convertible agora deteta autoatribuição (biblioteca padrão)
As versões anteriores do type-trait
std::is_convertablenão detetaram corretamente a autoatribuição de um tipo de classe quando o seu construtor de cópia é removido ou privado. Agora,std::is_convertable<>::valueestá corretamente definido comofalsequando aplicado a um tipo de classe com um construtor de cópia excluído ou particular.Não há nenhum diagnóstico de compilador associado a essa alteração.
Exemplo
#include <type_traits> class X1 { public: X1(const X1&) = delete; }; class X2 { private: X2(const X2&); }; static_assert(std::is_convertible<X1&, X1>::value, "BOOM");static_assert(std::is_convertible<X2&, X2>::value, "BOOM");Em versões anteriores do compilador, as asserções estáticas na parte inferior deste exemplo passam porque
std::is_convertable<>::valuefoi definido incorretamente comotrue. Agora,std::is_convertable<>::valueestá corretamente definido comofalse, fazendo com que as asserções estáticas falhem.Os construtores de cópia e movimentação triviais padrão ou excluídos respeitam os especificadores de acesso
As versões anteriores do compilador não verificavam o especificador de acesso de construtores de cópia e movimentação triviais padrão ou excluídos antes de permitir que eles fossem chamados. Esse comportamento antigo estava incorreto e não está em conformidade com o padrão C++. Em alguns casos, esse comportamento antigo criava um risco de geração silenciosa de código ruim, resultando em um comportamento de tempo de execução imprevisível. O compilador agora verifica o especificador de acesso de construtores triviais de cópia e movimentação padrão ou excluídos para determinar se podem ser chamados e, caso não possa, emite o aviso de compilador C2248.
error C2248: 'S::S' cannot access private member declared in class 'S'Exemplo (antes)
class S { public: S() = default; private: S(const S&) = default; }; void f(S); // pass S by value int main() { S s; f(s); // error C2248, can't invoke private copy constructor }Exemplo (depois)
class S { public: S() = default; private: S(const S&) = default; }; void f(const S&); // pass S by reference int main() { S s; f(s); }Descontinuação do suporte ao código ATL atribuído (Nível 1 (
/W1) on-by-default)Versões anteriores do compilador suportavam código ATL atribuído. Como a próxima fase de remoção do suporte ao código ATL atribuído que começou no Visual Studio 2008, o código ATL atribuído foi declarado obsoleto. O compilador agora emite um aviso do compilador C4467 para ajudar a identificar esse tipo de código preterido.
warning C4467: Usage of ATL attributes is deprecatedSe quiser continuar a usar o código ATL atribuído até que o suporte seja removido do compilador, pode desativar este aviso passando os argumentos de linha de comando
/Wv:18ou/wd:4467para o compilador ou adicionando#pragma warning(disable:4467)no seu código-fonte.Exemplo 1 (antes)
[uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")] class A {};Exemplo 1 (depois)
__declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) A {};Às vezes, você pode precisar ou querer criar um arquivo IDL para evitar o uso de atributos ATL preteridos, como no código de exemplo abaixo
Exemplo 2 (antes)
[emitidl]; [module(name = "Foo")]; [object, local, uuid("9e66a290-4365-11d2-a997-00c04fa37ddb")] __interface ICustom { HRESULT Custom([in] long l, [out, retval] long *pLong); [local] HRESULT CustomLocal([in] long l, [out, retval] long *pLong); }; [coclass, appobject, uuid("9e66a294-4365-11d2-a997-00c04fa37ddb")] class CFoo : public ICustom { // ... };Primeiro, crie o arquivo *.idl; O arquivo gerado VC140.idl pode ser usado para obter um arquivo *.idl contendo as interfaces e anotações.
Em seguida, adicione uma etapa MIDL à sua compilação para garantir que as definições de interface C++ sejam geradas.
Exemplo 2 IDL (depois)
import "docobj.idl"; [ object, local, uuid(9e66a290 - 4365 - 11d2 - a997 - 00c04fa37ddb) ] interface ICustom : IUnknown { HRESULT Custom([in] long l, [out, retval] long *pLong); [local] HRESULT CustomLocal([in] long l, [out, retval] long *pLong); }; [version(1.0), uuid(29079a2c - 5f3f - 3325 - 99a1 - 3ec9c40988bb)] library Foo { importlib("stdole2.tlb"); importlib("olepro32.dll"); [ version(1.0), appobject,uuid(9e66a294 - 4365 - 11d2 - a997 - 00c04fa37ddb) ] coclass CFoo { interface ICustom; }; }Em seguida, use ATL diretamente no arquivo de implementação, como no código de exemplo abaixo.
Implementação do Exemplo 2 (após)
#include <idl.header.h> #include <atlbase.h> class ATL_NO_VTABLE CFooImpl : public ICustom, public ATL::CComObjectRootEx< CComMultiThreadModel> { public: BEGIN_COM_MAP(CFooImpl) COM_INTERFACE_ENTRY(ICustom) END_COM_MAP() };Arquivos de cabeçalho (PCH) pré-compilados e diretivas #include incompatíveis (afeta
/Wall/WXapenas )As versões anteriores do compilador aceitavam diretivas
#includeincompatíveis em ficheiros de origem ao utilizar ficheiros de cabeçalho (PCH) pré-compilados entre compilações-Yce-Yu. O código escrito desta forma não é mais aceito pelo compilador. O compilador agora emite o aviso do compilador CC4598 para ajudar a identificar diretivas#includeincompatíveis ao usar arquivos PCH.warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that positionExemplo (antes):
X.cpp (-Ycc.h)
#include "a.h" #include "b.h" #include "c.h"Z.cpp (-Yuc.h)
#include "b.h" #include "a.h" // mismatched order relative to X.cpp #include "c.h"Exemplo (depois)
X.cpp (-Ycc.h)
#include "a.h" #include "b.h" #include "c.h"Z.cpp (-Yuc.h)
#include "a.h" #include "b.h" // matched order relative to X.cpp #include "c.h"Arquivos de cabeçalho (PCH) pré-compilados e diretórios de inclusão incompatíveis (afeta apenas
/Wall/WX)As versões anteriores do compilador aceitavam diretórios de inclusão incompatíveis como argumentos de linha de comando para o compilador entre as compilações de
-Ie-Ycao usar arquivos de cabeçalho pré-compilados (PCH). O código escrito desta forma não é mais aceito pelo compilador. O compilador agora emite aviso do compilador CC4599 para ajudar a identificar argumentos de linha de comando de diretório (-I) de inclusão incompatíveis ao usar arquivos PCH.warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that positionExemplo (antes)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cppExemplo (depois)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h -I.. Z.cpp
Alterações de conformidade do Visual Studio 2013
Compilador
A palavra-chave final agora gera um erro de símbolo não resolvido onde teria sido compilada anteriormente:
struct S1 { virtual void f() = 0; }; struct S2 final : public S1 { virtual void f(); }; int main(S2 *p) { p->f(); }Nas versões anteriores, não era emitido um erro porque a chamada era uma
virtual; no entanto, o programa travava durante o tempo de execução. Agora, um erro de vinculador é emitido porque a classe é conhecida por ser final. Neste exemplo, para corrigir o erro, deverás referenciar o obj que contém a definição deS2::f.Quando você usa funções friend em namespaces, você deve redeclarar a função friend antes de se referir a ela ou você receberá um erro porque o compilador agora está em conformidade com o padrão ISO C++. Por exemplo, este exemplo não compila mais:
namespace NS { class C { void func(int); friend void func(C* const) {} }; void C::func(int) { NS::func(this); // error } }Para corrigir este código, declare a
friendfunção:namespace NS { class C { void func(int); friend void func(C* const) {} }; void func(C* const); // conforming fix void C::func(int) { NS::func(this); }O padrão C++ não permite especialização explícita em uma classe. Embora o compilador Microsoft C++ permita isso em alguns casos, em casos como o exemplo a seguir, um erro agora é gerado porque o compilador não considera a segunda função como uma especialização da primeira.
template < int N> class S { public: template void f(T& val); template < > void f(char val); }; template class S< 1>;Para corrigir este código, modifique a segunda função:
template <> void f(char& val);O compilador não tenta mais desambiguar as duas funções no exemplo a seguir e agora emite um erro:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(); // error }Para corrigir este código, esclareça a chamada:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(nullptr); // ok }Antes de o compilador estar em conformidade com o ISO C++11, o código a seguir teria sido compilado e teria feito com que
xresolvesse para o tipoint.auto x = {0}; int y = x;Esse código agora resolve
xpara um tipo destd::initializer_list<int>e causa um erro na próxima linha que tenta atribuirxao tipoint. (Não há conversão por padrão.) Para corrigir esse código, useintpara substituirauto:int x = {0}; int y = x;A inicialização agregada não é mais permitida quando o tipo do valor do lado direito não corresponde ao tipo do valor do lado esquerdo que está sendo inicializado, e um erro é emitido porque o padrão ISO C++11 requer inicialização uniforme para funcionar sem restringir as conversões. Anteriormente, se uma conversão de estreitamento estivesse disponível, um aviso de Aviso do Compilador (nível 4) C4242 teria sido emitido em vez de um erro.
int i = 0; char c = {i}; // errorPara corrigir esse código, adicione uma conversão de estreitamento explícita:
int i = 0; char c = {static_cast<char>(i)};A seguinte inicialização não é mais permitida:
void *p = {{0}};Para corrigir esse código, use um destes formulários:
void *p = 0; // or void *p = {0};A pesquisa de nomes foi alterada. O código a seguir é resolvido de forma diferente no compilador C++ no Visual Studio 2012 e Visual Studio 2013:
enum class E1 { a }; enum class E2 { b }; int main() { typedef E2 E1; E1::b; }No Visual Studio 2012, a expressão
E1emE1::bfoi resolvida para::E1no escopo global. No Visual Studio 2013,E1na expressãoE1::bresolve-se para a definição detypedef E2emmain()e tem o tipo::E2.O layout do objeto foi alterado. Em x64, o layout do objeto de uma classe pode mudar em relação às versões anteriores. Se ele tiver uma
virtualfunção, mas não tiver uma classe base que tenha umavirtualfunção, o modelo de objeto do compilador insere um ponteiro para umavirtualtabela de funções após o layout do membro de dados. Isso significa que o layout pode não ser ideal em todos os casos. Em versões anteriores, uma otimização para x64 tentaria melhorar o layout para você, mas como não funcionou corretamente em situações de código complexas, foi removida no Visual Studio 2013. Por exemplo, considere este código:__declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };No Visual Studio 2013, o resultado de
sizeof(S2)em x64 é 48, mas em versões anteriores, ele é avaliado como 32. Para que isto avalie para 32 no compilador C++ do Visual Studio 2013 para x64, adicione uma classe base fictícia que contenha uma funçãovirtual:__declspec(align(16)) struct S1 { }; struct dummy { virtual ~dummy() {} }; struct S2 : public dummy { virtual ~S2(); void *p; S1 s; };Para encontrar lugares no seu código que uma versão anterior teria tentado otimizar, use um compilador dessa versão juntamente com a opção de compilador
/W3e ative o aviso C4370. Por exemplo:#pragma warning(default:4370) __declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };Antes do Visual Studio 2013, esse código gera esta mensagem: "aviso C4370: 'S2': layout da classe foi alterado de uma versão anterior do compilador devido a um melhor empacotamento".
O compilador x86 tem o mesmo problema de layout subótimo em todas as versões do compilador. Por exemplo, se este código for compilado para x86:
struct S { virtual ~S(); int i; double d; };O resultado de
sizeof(S)é 24. No entanto, ele pode ser reduzido para 16 se você usar a solução alternativa mencionada para x64:struct dummy { virtual ~dummy() {} }; struct S : public dummy { virtual ~S(); int i; double d; };
Biblioteca Standard
O compilador C++ no Visual Studio 2013 deteta incompatibilidades no _ITERATOR_DEBUG_LEVEL, que foi implementado no Visual Studio 2010, e incompatibilidades no RuntimeLibrary. Essas incompatibilidades ocorrem quando as opções /MT do compilador (versão estática), /MTd (depuração estática), /MD (versão dinâmica) e /MDd (depuração dinâmica) são misturadas.
Se o seu código reconhece os modelos de alias simulados da versão anterior, você precisa alterá-lo. Por exemplo, em vez de
allocator_traits<A>::rebind_alloc<U>::other, agora você tem que dizerallocator_traits<A>::rebind_alloc<U>. Emboraratio_add<R1, R2>::typejá não seja necessário e agora recomendemos que se digaratio_add<R1, R2>, o anterior ainda será compilado porque é necessário queratio<N, D>tenha um typedef "tipo" para uma proporção reduzida, que será do mesmo tipo se já estiver reduzida.Você deve usar
#include <algorithm>quando chamarstd::min()oustd::max().Se o código existente usa os enums com escopo simulado da versão anterior — enums tradicionais sem escopo encapsulados em namespaces — você precisa alterá-lo. Por exemplo, se você se referiu ao tipo
std::future_status::future_status, agora você tem que dizerstd::future_status. No entanto, a maioria dos códigos não é afetada — por exemplo,std::future_status::readyainda compila.explicit operator bool()é mais rigoroso do que o operador unspecified-bool-type().explicit operator bool()permite conversões explícitas para bool — por exemplo, dadoshared_ptr<X> sp, tantostatic_cast<bool>(sp)quantobool b(sp)são válidos — e "conversões contextuais" que podem ser testadas como bool — por exemplo,if (sp),!sp,sp &&seja qual for. No entanto,explicit operator bool()proíbe conversões implícitas para bool, então você não pode dizerbool b = sp;e dado um tipo de retorno bool, você não pode dizerreturn sp.Agora que modelos variádicos reais são implementados, _VARIADIC_MAX e macros relacionadas não têm efeito. Se você ainda está definindo _VARIADIC_MAX, ele é ignorado. Se você reconheceu nosso maquinário macro destinado a suportar modelos variádicos simulados de qualquer outra forma, você tem que alterar seu código.
Além das palavras-chave comuns, os cabeçalhos da Biblioteca Padrão C++ agora proíbem a substituição por macros das palavras-chave sensíveis ao contexto override e final.
reference_wrapper,ref()ecref()agora proíbem a vinculação a objetos temporários.<random>agora aplica estritamente suas pré-condições de tempo de compilação.Várias características de tipo de biblioteca padrão C++ têm a pré-condição "T deve ser um tipo completo". Embora o compilador agora imponha essa pré-condição de forma mais rigorosa, ele pode não impô-la em todas as situações. (Como as violações de pré-condição da Biblioteca Padrão C++ desencadeiam um comportamento indefinido, o Padrão não garante a aplicação.)
A biblioteca padrão do C++ não suporta
/clr:oldSyntax.A especificação C++11 para
common_type<>teve consequências inesperadas e indesejadas; em particular, fazcommon_type<int, int>::typeretornarint&&. Portanto, o compilador implementa a Resolução Proposta para a questão 2141 do Grupo de Trabalho de Biblioteca, que faz ocommon_type<int, int="">::typeretornar oint.Como efeito colateral dessa alteração, o caso de identidade não funciona mais (
common_type<T>nem sempre resulta em tipoT). Esse comportamento está em conformidade com a resolução proposta, mas quebra qualquer código que dependia do comportamento anterior.Se você precisar de uma característica de tipo de identidade, não use o não-padrão
std::identitydefinido em<type_traits>porque ele não funcionará para<void>. Em vez disso, implemente o seu próprio tipo de traço de identidade para atender às suas necessidades. Aqui está um exemplo:template < typename T> struct Identity { typedef T type; };
MFC e ATL
Somente Visual Studio 2013: MFC MBCS Library não está incluído no Visual Studio porque o Unicode é muito popular e o uso do MBCS diminuiu significativamente. Essa alteração também mantém o MFC mais alinhado com o próprio SDK do Windows, porque muitos dos novos controles e mensagens são somente Unicode. No entanto, se tiver de continuar a utilizar a biblioteca MFC MBCS, pode transferi-la a partir do Centro de Transferências da Microsoft em Multibyte MFC Library for Visual Studio 2013. O Visual C++ Redistributable Package ainda inclui esta biblioteca. (Observação: a DLL do MBCS está incluída nos componentes de instalação do C++ no Visual Studio 2015 e posterior).
A acessibilidade da faixa de opções do MFC foi modificada. Em vez de uma arquitetura de um nível, há agora uma arquitetura hierárquica. Você ainda pode usar o comportamento antigo chamando
CRibbonBar::EnableSingleLevelAccessibilityMode().O
CDatabase::GetConnectmétodo é removido. Para melhorar a segurança, a cadeia de conexão agora é armazenada criptografada e descriptografada apenas conforme necessário; ele não pode ser retornado como texto simples. A cadeia de caracteres pode ser obtida usando oCDatabase::Dumpmétodo.A assinatura do
CWnd::OnPowerBroadcasté alterada. A assinatura deste manipulador de mensagens é alterada para tomar um LPARAM como o segundo parâmetro.As assinaturas são alteradas para acomodar manipuladores de mensagens. As listas de parâmetros das seguintes funções foram alteradas para usar manipuladores de mensagens ON_WM_* recém-adicionados:
CWnd::OnDisplayChangealterado para (UINT, int, int) em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_DISPLAYCHANGE possa ser usada no mapa de mensagens.CFrameWnd::OnDDEInitiatealterado para (CWnd*, UINT, UNIT) em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_DDE_INITIATE possa ser usada no mapa de mensagens.CFrameWnd::OnDDEExecutefoi alterado para (CWnd*, HANDLE) em vez de (WPARAM, LPARAM), de modo que a nova macro ON_WM_DDE_EXECUTE possa ser utilizada no mapa de mensagens.CFrameWnd::OnDDETerminatefoi alterado para (CWnd*) como parâmetro, em vez de (WPARAM, LPARAM), de modo que a nova macro ON_WM_DDE_TERMINATE possa ser utilizada no mapa de mensagens.CMFCMaskedEdit::OnCutalterado para sem parâmetros em vez de (WPARAM, LPARAM) permitindo que a nova macro ON_WM_CUT seja usada no mapa de mensagens.CMFCMaskedEdit::OnClearfoi alterado para não usar parâmetros em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_CLEAR possa ser utilizada no mapa de mensagens.CMFCMaskedEdit::OnPastealterado para não ter parâmetros em vez de (WPARAM, LPARAM), para que a macro ON_WM_PASTE seja usada no mapa de mensagens.
#ifdefdiretivas nos ficheiros de cabeçalho MFC foram removidas. Várias#ifdefdiretivas nos arquivos de cabeçalho MFC relacionadas a versões não suportadas do Windows (WINVER < 0x0501) são removidas.ATL DLL (atl120.dll) é removida. ATL agora é fornecido como cabeçalhos e uma biblioteca estática (atls.lib).
Atlsd.lib, atlsn.lib e atlsnd.lib são removidos. Atls.lib não tem mais dependências de conjunto de caracteres ou código específico para depuração/lançamento. Como funciona da mesma forma para Unicode/ANSI e debug/release, apenas uma versão da biblioteca é necessária.
A ferramenta de rastreamento ATL/MFC é removida juntamente com a DLL ATL e o mecanismo de rastreamento é simplificado. O
CTraceCategoryconstrutor agora usa um parâmetro (o nome da categoria) e as macros TRACE chamam as funções de relatório de depuração CRT.
Alterações recentes do Visual Studio 2012
Compilador
A opção do
/Ylcompilador foi alterada. Por padrão, o compilador usa essa opção, o que pode levar a erros de LNK2011 sob certas condições. Para obter mais informações, consulte /Yl (Inject PCH Reference for Debug Library).No código que é compilado usando
/clr, aenumpalavra-chave class define um enum C++11, não um enum CLR (Common Language Runtime). Para definir um enum CLR, você deve ser explícito sobre sua acessibilidade.Use a palavra-chave template para desambiguar explicitamente um nome dependente (conformidade padrão da linguagem C++). No exemplo a seguir, a palavra-chave de modelo realçada é obrigatória para resolver a ambiguidade. Para obter mais informações, consulte Resolução de nomes para tipos dependentes.
template < typename X = "", typename = "" AY = ""> struct Container { typedef typename AY::template Rebind< X> ::Other AX; };A expressão constante do tipo float não é mais permitida como um argumento de modelo, conforme mostrado no exemplo a seguir.
template<float n=3.14> struct B {}; // error C2993: 'float': illegal type for non-type template parameter 'n'O código que é compilado usando a opção de linha de comando
/GSe que tem uma vulnerabilidade off-by-one pode levar ao encerramento do processo durante a execução, conforme mostrado no exemplo de pseudocódigo a seguir.char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminateA arquitetura padrão para compilações x86 é alterada para SSE2; portanto, o compilador pode emitir instruções SSE e usará os registradores XMM para executar cálculos de ponto flutuante. Se você quiser reverter para o comportamento anterior, use o sinalizador do
/arch:IA32compilador para especificar a arquitetura como IA32.O compilador pode emitir avisos Compiler Warning (nível 4) C4703 e C4701 onde anteriormente não o fazia. O compilador aplica verificações mais fortes para o uso de variáveis locais não inicializadas do tipo ponteiro.
Quando o novo sinalizador
/HIGHENTROPYVAde vinculador é especificado, o Windows 8 normalmente faz com que as alocações de memória retornem um endereço de 64 bits. (Antes do Windows 8, essas alocações geralmente retornavam endereços inferiores a 2 GB.) Esta alteração pode expor falhas de truncamento de ponteiros no código existente. Por padrão, essa opção está ativada. Para desativar esse comportamento, especifique/HIGHENTROPYVA:NO.O compilador gerenciado (Visual Basic/C#) também oferece suporte
/HIGHENTROPYVApara compilações gerenciadas. No entanto, neste caso, o/HIGHENTROPYVAswitchestá desativado por padrão.
IDE
- Embora seja recomendável que você não crie aplicativos do Windows Forms em C++/CLI, há suporte para a manutenção de aplicativos de interface do usuário C++/CLI existentes. Se você tiver que criar um aplicativo Windows Forms ou qualquer outro aplicativo .NET UI, use C# ou Visual Basic. Use C++/CLI apenas para fins de interoperabilidade.
Biblioteca de Padrões Paralelos e Biblioteca de Tempo de Execução de Concorrrência
A SchedulerType enumeração de UmsThreadDefault é preterida. A especificação de UmsThreadDefault produz um aviso descontinuado e remapeia internamente para ThreadScheduler.
Biblioteca Standard
Após uma alteração significativa entre os padrões C++98/03 e C++11, o uso de argumentos de modelo explícitos para chamar
make_pair()— como emmake_pair<int, int>(x, y)— normalmente não é compilado no Visual C++ no Visual Studio 2012. A solução é sempre chamarmake_pair()sem argumentos de modelo explícitos — como emmake_pair(x, y). Fornecer argumentos de modelo explícitos derrota o propósito da função. Se você precisar de controle preciso sobre o tipo resultante, usepairem vez demake_pair— como empair<short, short>(int1, int2).Outra mudança importante entre os padrões C++98/03 e C++11: Quando A é implicitamente conversível em B e B é implicitamente conversível em C, mas A não é implicitamente conversível em C, C++98/03 e Visual Studio 2010 permitiam que
pair<A, X>fosse convertido (implícita ou explicitamente) empair<C, X>. (O outro tipo, X, não é de interesse aqui, e não é específico para o primeiro tipo do par.) O compilador C++ no Visual Studio 2012 deteta que A não é implicitamente conversível para C e remove a conversão do par da resolução de sobrecarga. Esta mudança é positiva para muitos cenários. Por exemplo, sobrecarregarfunc(const pair<int, int>&)efunc(const pair<string, string>&), e chamarfunc()compair<const char *, const char *>será compilado com esta alteração. No entanto, essa alteração quebra o código que dependia de conversões de pares agressivas. Esse código normalmente pode ser corrigido executando uma parte da conversão explicitamente, por exemplo, passandomake_pair(static_cast<B>(a), x)para uma função que esperapair<C, X>.O Visual Studio 2010 simulou modelos variádicos, por exemplo,
make_shared<T>(arg1, arg2, argN)até um limite de 10 argumentos, eliminando sobrecargas e especializações com máquinas de pré-processador. No Visual Studio 2012, esse limite é reduzido para cinco argumentos para melhorar os tempos de compilação e o consumo de memória do compilador para a maioria dos usuários. No entanto, você pode definir o limite anterior definindo explicitamente _VARIADIC_MAX como 10, em todo o projeto.C++11 17.6.4.3.1 [macro.names]/2 proíbe a substituição de palavras-chave por macro quando cabeçalhos de biblioteca padrão C++ são incluídos. Os cabeçalhos agora emitem erros de compilador se detetarem palavras-chave substituídas por macro. (Definir _ALLOW_KEYWORD_MACROS permite que esse código seja compilado, mas desencorajamos fortemente esse uso.) Como exceção, a forma de macro de
newé permitida por padrão, porque os cabeçalhos se defendem de forma abrangente usando#pragma push_macro("new")/#undef new/#pragma pop_macro("new"). Definir _ENFORCE_BAN_OF_MACRO_NEW faz exatamente o que seu nome indica.Para implementar várias otimizações e verificações de depuração, a implementação da Biblioteca Padrão C++ quebra intencionalmente a compatibilidade binária entre versões do Visual Studio (2005, 2008, 2010, 2012). Quando a biblioteca padrão C++ é usada, ela proíbe a mistura de arquivos de objeto e bibliotecas estáticas que são compiladas usando versões diferentes em um binário (EXE ou DLL), e proíbe a passagem de objetos C++ Standard Library entre binários que são compilados usando versões diferentes. A mistura de ficheiros de objeto e bibliotecas estáticas (usando a Biblioteca Padrão C++ que foi compilada usando o Visual Studio 2010 com aqueles que foram compilados usando o compilador C++ no Visual Studio 2012 emite erros do linker sobre incompatibilidade de _MSC_VER, onde _MSC_VER é a macro que contém a versão principal do compilador (1700 para Visual C++ no Visual Studio 2012). Essa verificação não pode detetar a mistura de DLL e não pode detetar a mistura que envolve o Visual Studio 2008 ou anterior.
Além de detectar incompatibilidades de _ITERATOR_DEBUG_LEVEL, que foi implementado no Visual Studio 2010, o compilador C++ no Visual Studio 2012 também detecta incompatibilidades da Biblioteca de Runtime. Essas incompatibilidades ocorrem quando as opções
/MTdo compilador (versão estática),/MTd(depuração estática),/MD(versão dinâmica) e/MDd(depuração dinâmica) são misturadas.operator<(),operator>(),operator<=(), eoperator>=()estavam anteriormente disponíveis para asstd::unordered_mapfamílias destdext::hash_mapcontentores, embora as suas implementações não fossem úteis. Esses operadores não padrão foram removidos no Visual C++ no Visual Studio 2012. Além disso, a implementação deoperator==()eoperator!=()para a famíliastd::unordered_mapfoi estendida para abranger a famíliastdext::hash_map. (Recomendamos que você evite o uso dastdext::hash_mapfamília no novo código.)C++11 22.4.1.4 [locale.codecvt] especifica que
codecvt::length()ecodecvt::do_length()devem ter parâmetros modificáveisstateT&, mas o Visual Studio 2010 levouconst stateT&. O compilador C++ no Visual Studio 2012 levastateT&como exigido pelo padrão. Essa diferença é significativa para qualquer pessoa que esteja a tentar substituir a função virtualdo_length().
CRT
O heap C Runtime (CRT), que é usado para new e malloc(), não é mais privado. O CRT agora usa o heap de processo. Isso significa que o amontoado não é destruído quando uma DLL é descarregada, portanto, as DLLs que se vinculam estaticamente à CRT devem garantir que a memória alocada pelo código DLL seja limpa antes de a DLL ser descarregada.
A
iscsymf()função afirma com valores negativos.O
threadlocaleinfostructstruct foi alterado para acomodar as alterações nas funções de localidade.As funções CRT que têm intrínsecas correspondentes, como
memxxx(),strxxx()são removidas de intrin.h. Se você incluiu intrin.h apenas para essas funções, agora você deve incluir os cabeçalhos CRT correspondentes.
MFC e ATL
Suporte de fusão removido (afxcomctl32.h); portanto, todos os métodos definidos em
<afxcomctl32.h>foram removidos. Arquivos de cabeçalho<afxcomctl32.h>e<afxcomctl32.inl>foram excluídos.Alterado o nome de
CDockablePane::RemoveFromDefaultPaneDividierparaCDockablePane::RemoveFromDefaultPaneDivider.Alterada a assinatura de
CFileDialog::SetDefExtpara usar LPCTSTR, portanto, as compilações Unicode são afetadas.Removidas categorias obsoletas de rastreamento ATL.
Alterada a assinatura de
CBasePane::MoveWindowpara aceitar umconst CRect.Alterada a assinatura de
CMFCEditBrowseCtrl::EnableBrowseButton.Removido
m_fntTabsem_fntTabsBolddeCMFCBaseTabCtrl.Adicionado um parâmetro aos
CMFCRibbonStatusBarPaneconstrutores. (É um parâmetro padrão e, portanto, não quebra a fonte.)Adicionado um parâmetro ao
CMFCRibbonCommandsListBoxconstrutor. (É um parâmetro padrão e, portanto, não quebra a fonte.)Removida a API (
AFXTrackMousee o procedimento temporizador relacionado). Utilize a API do Win32TrackMouseEventem vez disso.Adicionado um parâmetro ao
CFolderPickerDialogconstrutor. (É um parâmetro padrão e, portanto, não quebra a fonte.)CFileStatustamanho da estrutura alterado: om_attributemembro foi alterado de BYTE para DWORD (para corresponder ao valor retornado deGetFileAttributes).CRichEditCtrleCRichEditViewuse MSFTEDIT_CLASS (controle RichEdit 4.1) em vez de RICHEDIT_CLASS (controle RichEdit 3.0) em compilações Unicode.Removido
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackgroundporque é sempre verdadeiro no Windows Vista, Windows 7 e Windows 8.Removido
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailableporque é sempre verdadeiro no Windows Vista, Windows 7 e Windows 8.Removido
AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. Chame a API do Windows diretamente no Windows Vista, Windows 7 e Windows 8.Removido
AFX_GLOBAL_DATA::DwmDefWindowProc. Chame a API do Windows diretamente no Windows Vista, Windows 7 e Windows 8.Renomeado
AFX_GLOBAL_DATA::DwmIsCompositionEnabledparaIsDwmCompositionEnabledpara eliminar a colisão de nomes.Alterou identificadores para vários temporizadores internos do MFC e moveu as definições para afxres.h (AFX_TIMER_ID_*).
Alterada a assinatura do método
OnExitSizeMovepara estar de acordo com a macro ON_WM_EXITSIZEMOVE:CFrameWndExCMDIFrameWndExCPaneFrameWnd
Alterado o nome e a assinatura de
OnDWMCompositionChangedpara concordar com a macro ON_WM_DWMCOMPOSITIONCHANGED.CFrameWndExCMDIFrameWndExCPaneFrameWnd
Alterada a assinatura do método
OnMouseLeavepara concordar com a macro ON_WM_MOUSELEAVE.CMFCCaptionBarCMFCColorBarCMFCHeaderCtrlCMFCProperySheetListBoxCMFCRibbonBarCMFCRibbonPanelMenuBarCMFCRibbonRichEditCtrlCMFCSpinButtonCtrlCMFCToolBarSubstituaEsteTextoCMFCToolBarComboBoxEditCMFCToolBarEditCtrlCMFCAutoHideBar
Alterada a assinatura de
OnPowerBroadcastpara concordar com a macro ON_WM_POWERBROADCAST:CFrameWndExCMDIFrameWndEx
Alterada a assinatura de
OnStyleChangedpara concordar com a macro ON_WM_STYLECHANGED:CMFCListCtrlCMFCStatusBar
Renomeado o método
FontFamalyProcFontsinterno paraFontFamilyProcFonts.Removidos vários objetos estáticos
CStringglobais para eliminar vazamentos de memória em algumas situações (substituídos por #defines) e as seguintes variáveis de membro de classe:CKeyBoardManager::m_strDelimiterCMFCPropertyGridProperty::m_strFormatCharCMFCPropertyGridProperty::m_strFormatShortCMFCPropertyGridProperty::m_strFormatLongCMFCPropertyGridProperty::m_strFormatUShortCMFCPropertyGridProperty::m_strFormatULongCMFCPropertyGridProperty::m_strFormatFloatCMFCPropertyGridProperty::m_strFormatDoubleCMFCToolBarImages::m_strPngResTypeCMFCPropertyGridProperty::m_strFormat
Alterada a assinatura de
CKeyboardManager::ShowAllAcceleratorse removido o parâmetro de delimitador do acelerador.Adicionado
CPropertyPage::GetParentSheet, e na classeCPropertyPage, chame-o em vez deGetParentpara obter a janela da planilha pai correta, que pode ser a janela pai ou uma janela avô deCPropertyPage. Talvez seja necessário alterar o código para chamarGetParentSheetem vez deGetParent.Corrigido pragma warning(push) desbalanceado no ATLBASE.H, causando a desativação incorreta de avisos. Esses avisos agora estão ativados corretamente após o ATLBASE. H foi analisado.
Métodos relacionados a D2D movidos de AFX_GLOBAL_DATA para _AFX_D2D_STATE:
GetDirectD2dFactoryGetWriteFactoryGetWICFactoryInitD2DReleaseD2DRefsIsD2DInitializedD2D1MakeRotateMatrixEm vez de ligar, por exemplo, para
afxGlobalData.IsD2DInitialized, ligue paraAfxGetD2DState->IsD2DInitialized.
Removidos os arquivos ATL*.CPP obsoletos da pasta \atlmfc\include\.
Inicialização movida
afxGlobalDatapara ser realizada sob demanda, em vez de durante a inicialização do CRT, para atender aos requisitos deDLLMain.Adicionado o
RemoveButtonByIndexmétodo àCMFCOutlookBarPaneclasse.Corrigido
CMFCCmdUsageCount::IsFreqeuntlyUsedCmdparaIsFrequentlyUsedCmd.Corrigidas várias instâncias de
RestoreOriginalstateparaRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).Métodos não utilizados removidos de
CDockablePane:SetCaptionStyle,IsDrawCaption,IsHideDisabledButtons,GetRecentSiblingPaneInfo, eCanAdjustLayout.Removidas
CDockablePaneas variáveism_bCaptionTextde membro estático em_bHideDisabledButtons.Adicionou-se uma função de override
DeleteStringaoCMFCFontComboBox.Métodos não utilizados removidos de
CPane:GetMinLengtheIsLastPaneOnLastRow.Renomeado
CPane::GetDockSiteRow(CDockingPanesRow *)paraCPane::SetDockSiteRow.
Alterações recentes do Visual Studio 2010
Compilador
A
autopalavra-chave tem um novo significado padrão. Como o uso do significado antigo é raro, a maioria dos aplicativos não será afetada por essa alteração.Foi introduzida a nova palavra-chave
static_assert, que provocará um conflito de nome caso já exista um identificador com esse nome no seu código.O suporte para a nova notação lambda exclui o suporte para codificação de um GUID não citado em um atributo uuid IDL.
O .NET Framework 4 introduz o conceito de exceções de estado corrompido, que são exceções que deixam um processo em um estado corrompido irrecuperável. Por padrão, você não pode capturar uma exceção de estado corrompido, mesmo com a opção de compilador /EHa que captura todas as outras exceções. Para capturar explicitamente uma exceção de estado corrompido, utilize as instruções __try-__except. Ou, aplique o atributo [HandledProcessCorruptedStateExceptions] para permitir que uma função capture exceções de estado corrompido. Essa alteração afeta principalmente os programadores de sistema que podem ter que capturar uma exceção de estado corrompido. As oito exceções são STATUS_ACCESS_VIOLATION, STATUS_STACK_OVERFLOW, EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_INVALID_DISPOSITION, EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_PRIV_INSTRUCTION, STATUS_UNWIND_CONSOLIDATE. Para obter mais informações sobre essas exceções, consulte a macro GetExceptionCode .
A opção de compilador revisada
/GSprotege contra saturações de buffer de forma mais abrangente do que em versões anteriores. Esta versão pode inserir verificações de segurança adicionais na pilha que podem diminuir o desempenho. Use a nova__declspec(safebuffers)palavra-chave para instruir o compilador a não inserir verificações de segurança para uma função específica.Se compilar com
/GL(Whole Program Optimization) e/clr(Common Language Runtime Compilation), a opção/GLserá ignorada. Esta alteração foi feita porque a combinação de opções do compilador proporcionou poucos benefícios. Como resultado dessa mudança, o desempenho da compilação é melhorado.Por padrão, o suporte para trigrafos está desabilitado no Visual Studio 2010. Use a opção do compilador
/Zc:trigraphspara ativar o suporte a trigrafos. Um trígrafo consiste em dois pontos de interrogação consecutivos ("??") seguidos por um terceiro caractere único. O compilador substitui um trígrafo com um caractere de pontuação correspondente. Por exemplo, o compilador substitui o trígrafo??=pelo caractere '#'. Use trigrafos em arquivos de origem C que usam um conjunto de caracteres que não contém representações gráficas convenientes para alguns caracteres de pontuação.O vinculador não suporta mais a otimização para o Windows 98. A
/OPTopção (Otimizações) produz um erro de tempo de compilação se você especificar/OPT:WIN98ou/OPT:NOWIN98.As opções padrão do compilador especificadas pelas propriedades do sistema de compilação RuntimeLibrary e DebugInformationFormat foram alteradas. Por padrão, essas propriedades de compilação são especificadas em projetos criados pelo Visual C++ versões 7.0 a 10.0. Se você migrar um projeto que foi criado pelo Visual C++ 6.0, considere se deseja especificar um valor para essas propriedades.
No Visual Studio 2010, RuntimeLibrary = MultiThreaded (
/MD) e DebugInformationFormat = ProgramDatabase (/Zi). Em Visual C++ 9.0, RuntimeLibrary = Multithreaded (/MT) e DebugInformationFormat = Desativado.
CLR (Common Language Runtime)
- Os compiladores Microsoft C# e Visual Basic agora podem produzir um assembly sem interoperabilidade primária. Um assembly no-PIA pode usar tipos COM sem precisar da implantação do assembly de interoperabilidade primário (PIA) relevante. Ao consumir assemblies no-PIA produzidos pelo Visual C# ou Visual Basic, você deve fazer referência ao assembly PIA no comando compile antes de fazer referência a qualquer assembly no-PIA que usa a biblioteca.
Projetos do Visual Studio C++ e MSBuild
Projetos do Visual Studio C++ agora são baseados na ferramenta MSBuild. Consequentemente, os arquivos de projeto usam um novo formato de arquivo XML e um sufixo de arquivo .vcxproj. Visual Studio 2010 converte automaticamente arquivos de projeto de versões anteriores do Visual Studio para o novo formato de arquivo. Um projeto existente é afetado se depender da ferramenta de compilação anterior, VCBUILD.exeou sufixo do arquivo de projeto, .vcproj.
Em versões anteriores, o Visual C++ suportava a avaliação tardia de folhas de propriedades. Por exemplo, uma folha de propriedades pai pode importar uma folha de propriedades filho e o pai pode usar uma variável definida no filho para definir outras variáveis. A avaliação tardia permitiu que o pai usasse a variável da criança antes mesmo de a folha de propriedades da criança ser importada. No Visual Studio 2010, uma variável de planilha de projeto não pode ser usada antes de ser definida porque o MSBuild oferece suporte apenas à avaliação inicial.
IDE
A caixa de diálogo de encerramento do aplicativo não encerra mais um aplicativo. Em versões anteriores, quando a função
abort()outerminate()fechava a compilação de retalho de um aplicativo, a Biblioteca C Run-Time exibia uma mensagem de encerramento do aplicativo numa janela ou caixa de diálogo do console. A mensagem dizia em parte: "Este aplicativo solicitou ao Runtime para encerrá-lo de uma maneira incomum. Entre em contato com a equipe de suporte do aplicativo para obter mais informações." A mensagem de encerramento do aplicativo era redundante porque o Windows exibia subsequentemente o manipulador de terminação atual, que geralmente era a caixa de diálogo Relatório de Erros do Windows (Dr. Watson) ou o depurador do Visual Studio. A partir do Visual Studio 2010, a Biblioteca Run-Time C não exibe a mensagem. Além disso, o tempo de execução impede que o aplicativo termine antes que um depurador seja iniciado. Esta é uma alteração significativa apenas se dependeres do comportamento anterior da mensagem de encerramento da aplicação.Especificamente para o Visual Studio 2010, o IntelliSense não funciona para código ou atributos C++/CLI, Localizar Todas as Referências não funciona para variáveis locais e o Modelo de Código não recupera nomes de tipo de assemblies importados ou resolve tipos para seus nomes totalmente qualificados.
Bibliotecas
A classe SafeInt está incluída no Visual C++ e não está mais em um download separado. Esta é uma alteração significativa somente se desenvolveu uma classe que também se chama "SafeInt".
O modelo de implantação de bibliotecas não usa mais manifestos para localizar uma versão específica de uma biblioteca de vínculo dinâmico. Em vez disso, o nome de cada biblioteca de vínculo dinâmico contém seu número de versão e você usa esse nome para localizar a biblioteca.
Em versões anteriores do Visual Studio, você podia reconstruir as bibliotecas de tempo de execução. Visual Studio 2010 deixou de suportar a criação de cópias próprias dos arquivos da biblioteca de tempo de execução C.
Biblioteca Standard
O
<iterator>cabeçalho não é mais incluído automaticamente por muitos outros arquivos de cabeçalho. Em vez disso, inclua esse cabeçalho explicitamente se precisar de suporte para os iteradores autônomos definidos no cabeçalho. Um projeto existente é afetado se depender da ferramenta de compilação anterior, VCBUILD.exe, ou do sufixo do arquivo de projeto, .vcproj.iterator.No cabeçalho
<algorithm>, as funçõeschecked_*eunchecked_*são removidas. E no<iterator>> cabeçalho, achecked_iteratorclasse é removida e aunchecked_array_iteratorclasse foi adicionada.O
CComPtr::CComPtr(int)construtor é removido. Esse construtor permitia que umCComPtrobjeto fosse construído a partir da macro NULL, mas era desnecessário e permitia construções absurdas de inteiros diferentes de zero.Um
CComPtrainda pode ser construído a partir de NULL, que é definido como 0, mas falhará se for construído a partir de um número inteiro que não seja exatamente 0. Utilizenullptrem substituição.As seguintes
ctypefunções de membro foram removidas:ctype::_Do_narrow_s,ctype::_Do_widen_s,ctype::_narrow_s,ctype::_widen_s. Se um aplicativo usa uma dessas funções de membro, você deve substituí-lo pela versão não segura correspondente:ctype::do_narrow,ctype::do_widen,ctype::narrow,ctype::widen.
Bibliotecas CRT, MFC e ATL
O suporte foi removido para que os usuários criem as bibliotecas CRT, MFC e ATL. Por exemplo, nenhum arquivo NMAKE apropriado é fornecido. No entanto, os usuários ainda têm acesso ao código-fonte dessas bibliotecas. E um documento que descreve as opções do MSBuild que a Microsoft usa para criar essas bibliotecas provavelmente será postado em um blog da equipe do Visual C++.
O suporte MFC para IA64 foi removido. No entanto, o suporte para o CRT e ATL no IA64 ainda é fornecido.
Os ordinais não são mais reutilizados em arquivos de definição de módulo (.def) MFC. Essa alteração significa que os ordinais não serão diferentes entre versões secundárias e a compatibilidade binária para service packs e versões de engenharia de correção rápida será melhorada.
Uma nova função virtual foi adicionada à
CDocTemplateclasse. Esta nova função virtual é CDocTemplate Class. A versão anterior doOpenDocumentFiletinha dois parâmetros. A nova versão tem três parâmetros. Para suportar o gestor de reinício, qualquer classe derivada deCDocTemplatedeve implementar a versão que tem três parâmetros. O novo parâmetro ébAddToMRU.
Macros e variáveis de ambiente
- A variável de ambiente __MSVCRT_HEAP_SELECT não é mais suportada. Esta variável de ambiente é removida e não há substituição.
Referência do Microsoft Macro Assembler
- Várias diretivas foram removidas do compilador Microsoft Macro Assembler Reference. As diretivas suprimidas são
.186,.286,.286P,.287,.8086,.8087e.NO87.
Alterações recentes do Visual Studio 2008
Compilador
As plataformas Windows 95, Windows 98, Windows ME e Windows NT não são mais suportadas. Esses sistemas operacionais foram removidos da lista de plataformas alvo.
O compilador não suporta mais vários atributos que estavam diretamente associados ao ATL Server. Os seguintes atributos não são mais suportados:
perf_counter
perf_object
Perfmon
manipulador_de_pedidos
soap_handler
soap_header
método SOAP
tag_name
Projetos do Visual Studio C++
Ao atualizar projetos de versões anteriores do Visual Studio, talvez seja necessário modificar as macros WINVER e _WIN32_WINNT para que elas sejam maiores ou iguais a 0x0500.
A partir do Visual Studio 2008, o assistente para novos projetos não tem uma opção para criar um projeto SQL Server em C++. Os projetos do SQL Server criados usando uma versão anterior do Visual Studio ainda serão compilados e funcionarão corretamente.
O arquivo de cabeçalho da API do Windows Winable.h foi removido. Inclua Winuser.h em vez disso.
A biblioteca de API do Windows Rpcndr.lib foi removida. Link com rpcrt4.lib em vez disso.
CRT
O suporte para Windows 95, Windows 98, Windows Millennium Edition e Windows NT 4.0 foi removido.
As seguintes variáveis globais foram removidas:
_osplatform
_osver
_winmajor
_winminor
_winver
As seguintes funções foram removidas. Use as funções da API do Windows
GetVersionouGetVersionExem vez disso:_get_osplatform
_get_osver
_get_winmajor
_get_winminor
_get_winver
A sintaxe das Anotações SAL foi alterada. Para obter mais informações, consulte Anotações SAL.
O filtro IEEE agora suporta o conjunto de instruções SSE 4.1. Para obter mais informações, consulte
_fpieee_flt.As bibliotecas de Run-Time C fornecidas com o Visual Studio não são mais dependentes da DLL do sistema msvcrt.dll.
Biblioteca Standard
O suporte para Windows 95, Windows 98, Windows Millennium Edition e Windows NT 4.0 foi removido.
Ao compilar no modo de depuração com _HAS_ITERATOR_DEBUGGING definido (substituído por _ITERATOR_DEBUG_LEVEL após o Visual Studio 2010), um programa agora lançará uma asserção quando um iterador tenta incrementar ou decrementar além dos limites do contêiner subjacente.
A variável membro c da classe Stack agora é declarada protegida. Anteriormente, esta variável membro era declarada pública.
O comportamento do
money_get::do_getmudou. Anteriormente, ao analisar uma quantidade monetária com mais dígitos fracionários do que são exigidos pelafrac_digits,do_getcostumava consumi-los todos. Agora,do_getpara de analisar depois de consumir no máximofrac_digitscaracteres.
ATL
O ATL não pode ser construído sem uma dependência do CRT. Em versões anteriores do Visual Studio, você poderia usar #define ATL_MIN_CRT para tornar um projeto ATL minimamente dependente do CRT. No Visual Studio 2008, todos os projetos ATL são minimamente dependentes da CRT, independentemente de ATL_MIN_CRT estar definida.
A base de código do servidor ATL foi lançada como um projeto de código-fonte compartilhado no CodePlex e não está instalada como parte do Visual Studio. Classes de codificação e decodificação de dados de atlenc.h e funções de utilidade e classes de atlutil.h e atlpath.h foram mantidas e agora fazem parte da biblioteca ATL. Vários arquivos associados ao ATL Server não fazem mais parte do Visual Studio.
Algumas funções não estão mais incluídas na DLL. Eles ainda estão localizados na biblioteca de importação. Isso não afetará o código que usa as funções estaticamente. Isso afetará apenas o código que usa essas funções dinamicamente.
As macros PROP_ENTRY e PROP_ENTRY_EX foram preteridas e substituídas pelas macros PROP_ENTRY_TYPE e PROP_ENTRY_TYPE_EX por motivos de segurança.
Classes compartilhadas ATL/MFC
O ATL não pode ser construído sem uma dependência do CRT. Em versões anteriores do Visual Studio, você poderia usar
#define ATL_MIN_CRTpara tornar um projeto ATL minimamente dependente do CRT. No Visual Studio 2008, todos os projetos ATL são minimamente dependentes da CRT, independentemente de ATL_MIN_CRT estar definida.A base de código do servidor ATL foi lançada como um projeto de código-fonte compartilhado no CodePlex e não está instalada como parte do Visual Studio. Classes de codificação e decodificação de dados de atlenc.h e funções de utilidade e classes de atlutil.h e atlpath.h foram mantidas e agora fazem parte da biblioteca ATL. Vários arquivos associados ao ATL Server não fazem mais parte do Visual Studio.
Algumas funções não estão mais incluídas na DLL. Eles ainda estão localizados na biblioteca de importação. Isso não afetará o código que usa as funções estaticamente. Isso afetará apenas o código que usa essas funções dinamicamente.
MFC
CTimeClasse: ACTimeclasse agora aceita datas a partir de 1/1/1900 d.C. em vez de 1/1/1970 d.C.Ordem de tabulação dos controles nas caixas de diálogo MFC: A ordem de tabulação correta de vários controles em uma caixa de diálogo MFC será perturbada se um controle ActiveX MFC for inserido na ordem de tabulação. Esta alteração corrige esse problema.
Por exemplo, crie um aplicativo de diálogo MFC que tenha um controle ActiveX e vários controles de edição. Posicione o controle ActiveX no meio da ordem de tabulação dos controles de edição. Inicie o aplicativo, clique em um controle de edição cuja ordem de tabulação está após o controle ActiveX e, em seguida, na guia. Antes dessa alteração, o foco era para o controle de edição seguindo o controle ActiveX em vez do próximo controle de edição na ordem de tabulação.
CFileDialogClasse: Os modelos personalizados para aCFileDialogclasse não podem ser portados automaticamente para o Windows Vista. Eles ainda são utilizáveis, mas não terão a funcionalidade adicional ou a aparência das caixas de diálogo de estilo do Windows Vista.CWndClass eCFrameWndClass: OCWnd::GetMenuBarInfométodo foi removido.O
CFrameWnd::GetMenuBarInfométodo agora é um método não virtual. Para obter mais informações, consulte Função GetMenuBarInfo no SDK do Windows.Suporte a ISAPI do MFC: O MFC não suporta mais a criação de aplicativos com a ISAPI (Internet Server Application Programming Interface). Se você quiser criar um aplicativo ISAPI, chame as extensões ISAPI diretamente.
APIs ANSI preteridas: As versões ANSI de vários métodos MFC foram preteridas. Use as versões Unicode desses métodos em seus aplicativos futuros. Para obter mais informações, consulte Requisitos de compilação para controles comuns do Windows Vista.
Alterações recentes do Visual Studio 2005
CRT
Muitas funções foram preteridas. Consulte Funções CRT preteridas.
Muitas funções agora validam seus parâmetros, interrompendo a execução se dados parâmetros inválidos. Essa validação pode quebrar o código que passa parâmetros inválidos e depende da função ignorá-los ou apenas retornar um código de erro. Consulte Validação de parâmetros.
O valor do descritor de arquivo -2 agora é usado para indicar isso
stdoutestderrnão estão disponíveis para saída, por exemplo, em um aplicativo do Windows que não tem janela de console. O valor utilizado anteriormente foi -1. Para obter mais informações, consulte _fileno.As bibliotecas CRT de thread único (libc.lib e libcd.lib) foram removidas. Utilize as bibliotecas CRT multithread. O
/MLsinalizador do compilador não é mais suportado. Versões sem bloqueio de algumas funções foram adicionadas nos casos em que a diferença de desempenho entre o código multithreaded e o código single-threaded é potencialmente significativa.A sobrecarga da função pow, double pow(int, int), foi removida para melhor se adequar ao padrão.
O especificador de formato %n não é mais suportado por padrão em nenhuma das funções da família printf porque é inerentemente inseguro. Se %n for encontrado, o comportamento padrão é invocar o manipulador de parâmetros inválido. Para habilitar o suporte %n, utilize
_set_printf_count_output(também consulte_get_printf_count_output).sprintfagora imprime o sinal negativo de um zero assinado.swprintffoi alterado para estar em conformidade com a Norma; agora requer um parâmetro de tamanho. A forma deswprintfsem o parâmetro de tamanho foi descontinuada._set_security_error_handlerfoi removido. Remova todas as chamadas para essa função; O manipulador padrão é uma maneira muito mais segura de lidar com erros de segurança.time_té agora um valor de 64 bits (a menos que _USE_32BIT_TIME_T esteja definido).As funções
_spawn,_wspawnagora deixamerrnointocado em caso de sucesso, conforme especificado pelo Padrão C.O RTC agora usa caracteres largos por padrão.
As funções de suporte a palavras de controle de ponto flutuante foram descontinuadas para aplicações compiladas com
/CLRou/CLR:PURE. As funções afetadas são_clear87,_clearfp,_control87,_controlfp, ,_fpreset_status87,_statusfp. Você pode desativar o aviso de descontinuação definindo _CRT_MANAGED_FP_NO_DEPRECATE, mas o uso dessas funções no código gerenciado é imprevisível e sem suporte.Algumas funções agora retornam ponteiros const. O antigo comportamento não-constante pode ser restabelecido ao definir _CONST_RETURN. As funções afetadas são
memchr, wmemchr
strchr, wcschr, _mbschr, _mbschr_l
strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l
strrchr, wcsrchr, _mbsrchr, _mbsrchr_l
strstr, wcsstr, _mbsstr, _mbsstr_l
Ao vincular com Setargv.obj ou Wsetargv.obj, não é mais possível suprimir a expansão de um caractere curinga na linha de comando colocando-o entre aspas duplas. Para obter mais informações, consulte Expandindo argumentos curinga.
Biblioteca Standard (2005)
A classe de exceção (localizada no
<exception>cabeçalho) foi movida para ostdnamespace. Em versões anteriores, essa classe estava no namespace global. Para resolver quaisquer erros que indiquem que a classe de exceção não pode ser encontrada, adicione a seguinte instrução using ao seu código:using namespace std;Ao chamar
valarray::resize(), o conteúdo devalarrayserá perdido e substituído por valores padrão. Oresize()método destina-se a reinicializar ovalarrayem vez de cultivá-lo dinamicamente como um vetor.Debug Iterators: Aplicativos criados com uma versão de depuração da C-Runtime Library e que usam iteradores incorretamente podem começar a ver asserções em tempo de execução. Para desabilitar essas declarações, você deve definir _HAS_ITERATOR_DEBUGGING (substituído por
_ITERATOR_DEBUG_LEVELapós o Visual Studio 2010) como 0. Para obter mais informações, consulte Debug Iterator Support
Alterações recentes do Visual C++ .NET 2003
Compilador
Agora são necessários parênteses de encerramento para a diretiva de pré-processador especificada (C2004).
As especializações explícitas não encontram mais parâmetros de modelo do modelo primário (Erro de compilador C2146).
Um membro protegido (n) só pode ser acessado através de uma função de membro de uma classe (B) que herda da classe (A) da qual ele (n) é membro (Erro de compilador C2247).
Verificações de acessibilidade aprimoradas no compilador agora detetam classes base inacessíveis (Erro do compilador C2248).
Uma exceção não pode ser capturada se o destrutor e/ou o construtor de cópia estiver inacessível (C2316).
Argumentos padrão em ponteiros para funções não são mais permitidos (erro de compilador C2383).
Um membro de dados estáticos não pode ser inicializado por meio de classe derivada (erro de compilador C2477).
A inicialização de um
typedefnão é permitida pelo padrão e agora gera um erro de compilador (Erro de compilador C2513).boolé agora um tipo adequado (erro de compilador C2632).Um UDC pode agora criar ambiguidade com operadores sobrecarregados (C2666).
Mais expressões são agora consideradas constantes de ponteiro nulo válidas (Erro de compilador C2668).
template<> agora é necessário em locais onde o compilador antes o implicaria (Erro do compilador C2768).
A especialização explícita de uma função de membro fora da classe não é válida se a função já tiver sido explicitamente especializada por meio de uma especialização de classe de modelo (Erro de compilador C2910).
Parâmetros de modelo não-tipo de ponto flutuante não são mais permitidos (Erro do compilador C2993).
Os modelos de classe não são permitidos como argumentos de tipo de modelo (C3206).
Os nomes das funções friend já não são introduzidos no namespace envolvente (Erro de Compilador C3767).
O compilador não aceitará mais vírgulas extras em uma macro (C4002).
Um objeto do tipo POD construído com um inicializador do formulário () será inicializado por padrão (C4345).
typename agora é necessário se um nome dependente deve ser tratado como um tipo (Aviso do compilador (nível 1) C4346).
Funções que foram incorretamente consideradas especializações de modelo não são mais consideradas assim (C4347).
Os membros de dados estáticos não podem ser inicializados por meio da classe derivada (C4356).
Uma especialização de modelo de classe precisa ser definida antes de ser usada em um tipo de retorno (Aviso do compilador (nível 3) C4686).
O compilador agora relata código inacessível (C4702).