Histórico de alterações do Microsoft C/C++ de 2003 a 2015
Este artigo descreve todas as alterações significativas, partindo do Visual Studio 2015 e voltando até o Visual Studio 2003 e os termos "novo comportamento" ou "agora" neste artigo referem-se ao Visual Studio 2015 e às versões posteriores. 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, confira Novidades do C++ no Visual Studio e Melhorias de conformidade de C++ no Visual Studio.
Observação
Não há alterações significativas binárias entre o Visual Studio 2015 e Visual Studio 2017.
Ao fazer a atualização para uma nova versão do Visual Studio, você pode encontrar erros de compilação e/ou de runtime no código que foi compilado anteriormente e executado corretamente. As alterações na nova versão que causam tais problemas são conhecidas como alterações significativas e, normalmente, são exigidas pelas modificações no padrão da linguagem C++, nas assinaturas de função ou no layout de objetos na memória.
Para evitar os erros de tempo de execução que são difíceis de detectar e diagnosticar, é recomendável nunca vincular estaticamente a binários compilados usando uma versão diferente do compilador. Além disso, ao fazer atualização de um projeto EXE ou DLL, assegure-se de atualizar as bibliotecas às quais ele se vincula. Não passe tipos CRT (Runtime de C) ou de Biblioteca do C++ Standard entre binários (incluindo DLLs) compilados usando diferentes versões do compilador. Para obter mais informações, consulte Erros potenciais ao passar objetos CRT entre limites de DLL.
Você nunca deve escrever código que dependa de um determinado layout de um objeto que não seja uma interface COM ou um objeto POD. Se você escrever tal código, será preciso garantir que ele funcione após a atualização. Para obter mais informações, consulte Portabilidade em limites ABI.
Além disso, aprimoramentos contínuos para a conformidade do compilador podem alterar como o compilador compreende seu código-fonte existente. Por exemplo, você poderá encontrar erros novos ou diferentes durante o build ou até diferenças de comportamento no código que foi compilado anteriormente e parecia executar corretamente. Embora essas melhorias não sejam alterações da falha, ao contrário daquelas discutidas neste documento, pode ser necessário fazer alterações no código-fonte para resolver estes problemas:
Alterações de conformidade do Visual Studio 2015
CRT (biblioteca de runtime 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 uma Biblioteca em Tempo de Execução do VC (vcruntime). A biblioteca vcruntime contém a funcionalidade relacionada ao compilador, como tratamento de exceção e intrínsecos. Se você estiver usando as configurações padrão de projeto, essa alteração não afetará você, pois o vinculador usa automaticamente as novas bibliotecas padrão. Se tiver definido a propriedade Ignorar Todas as Bibliotecas Padrão do Vinculador do projeto como Sim ou se estiver usando a opção de vinculador
/NODEFAULTLIB
na linha de comando, você deverá atualizar sua lista de bibliotecas (na propriedade Dependências Adicionais) para incluir as novas bibliotecas refatoradas. Substitua a biblioteca CRT antiga (libcmt.lib
,libcmtd.lib
,msvcrt.lib
,msvcrtd.lib
) pelas bibliotecas refatoradas equivalentes. Para cada uma das duas bibliotecas refatoradas, há versões estáticas (.lib) e dinâmicas (.dll) e versões release (sem sufixo) e versões de depuração (com o sufixo "d"). As versões dinâmicas têm uma biblioteca de importação com a qual você faz o vínculo. As duas bibliotecas refatoradas são CRT Universal, especificamente ucrtbase.dll ou ucrtbase.lib, ucrtbased.dll ou ucrtbased.lib e a biblioteca de tempo de execução do VC,libvcruntime.lib
, vcruntimeversão.dll,libvcruntimed.lib
e vcruntimedversão.dll. A versão no Visual Studio 2015 e no Visual Studio 2017 é 140. Consulte Recursos da biblioteca CRT.
<locale.h>
localeconv
A função
localeconv
declarada em locale.h agora funciona corretamente quando localidade por thread está habilitada. Nas versões anteriores da biblioteca, essa função retornaria os dadoslconv
para a localidade global e não para a localidade do thread.Se usar localidades por thread, você deverá verificar o uso de
localeconv
. Se o código pressupõe que os dados delconv
retornados são para a localidade global, você deve corrigi-lo.
<math.h>
Sobrecargas de C++ de funções de biblioteca de matemática
Nas versões anteriores,
<math.h>
definia algumas, mas não todas, sobrecargas de C++ para as funções de biblioteca de matemática. O restante das sobrecargas estavam no cabeçalho<cmath>
. O código que incluía somente<math.h>
poderia ter problemas com resolução de sobrecarga de função. Agora, as sobrecargas de C++ foram removidas de<math.h>
e estão presentes apenas em<cmath>
.Para resolver os erros, inclua
<cmath>
para obter as declarações das funções que foram removidas de<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)
- Versões
float
elong double
das funções de ponto flutuanteacos
,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ê tem código que usa
abs
com um tipo de ponto flutuante que inclui apenas o cabeçalho<math.h>
, as versões de ponto flutuante não estarão mais disponíveis. A chamada agora resolve paraabs(int)
, mesmo com um argumento de ponto flutuante, que produz o erro:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of data
A correção para esse aviso é substituir a chamada de
abs
por uma versão de ponto flutuante deabs
, comofabs
para um argumento double oufabsf
para um argumento float, ou incluir o cabeçalho<cmath>
e continuar usandoabs
.Conformidade de ponto flutuante
Muitas alterações foram feitas à biblioteca de matemática para melhorar a conformidade com as especificações IEEE-754 e C11 Anexo F em relação a entradas de caso especial, como NaNs e infinitos. Por exemplo, as entradas silenciosas de NaN, que geralmente eram tratadas como erros nas versões anteriores da biblioteca, não são mais tratadas como erros. Consulte o Padrão IEEE 754 e o Anexo F do Padrão C11.
Essas alterações não causarão erros de tempo de compilação, mas poderão fazer com que os programas se comportem de maneira diferente e de maneira mais correta de acordo com o padrão.
FLT_ROUNDS
No Visual Studio 2013, a macro FLT_ROUNDS expandia-se para uma expressão constante, o que era incorreto, porque o modo de arredondamento é configurável no runtime, por exemplo, pela chamada de fesetround. A macro FLT_ROUNDS agora é dinâmica e reflete corretamente o modo de arredondamento atual.
<new>
e <new.h>
new
edelete
Nas versões anteriores da biblioteca, as funções new e delete do operador definido pela implementação foram exportadas da biblioteca de runtime DLL (por exemplo, msvcr120.dll). Essas funções de operador agora estão sempre vinculadas estaticamente em seus binários, mesmo ao usar as bibliotecas de runtime DLLs.
Essa não é uma alteração da falha para o código nativo ou misto (
/clr
), no entanto, para o código compilado como /clr:pure, essa alteração pode causar falha ao compilar seu código. Se você compilar o código como/clr:pure
, talvez seja necessário adicionar#include <new>
ou#include <new.h>
para contornar erros de build devidos a essa alteração. A opção/clr:pure
foi preterida no Visual Studio 2015 e não tem suporte no Visual Studio 2017. Os códigos que precisarem ser "puros" deverão ser movidos para C#.
<process.h>
_beginthread
e_beginthreadex
As funções
_beginthread
e_beginthreadex
agora mantê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_start
e tipos de referênciaAo compilar código C++, o
va_start
agora valida em tempo de compilação que o argumento passado para ele não é de 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 são definidas embutidas.
As definições de todas as funções
printf
escanf
foram movidas embutidas para<stdio.h>
,<conio.h>
e outros cabeçalhos de CRT. Essa alteração da falha leva a um erro de vinculador (LNK2019, símbolo externo não resolvido) para todos os programas que declararam essas funções localmente, sem incluir os cabeçalhos de CRT apropriados. Se possível, você deve atualizar o código para incluir os cabeçalhos de CRT (ou seja, adicionar#include <stdio.h>
) e as funções embutidas, mas, se você não deseja modificar o código para incluir esses arquivos de cabeçalho, uma solução alternativa é adicionarlegacy_stdio_definitions.lib
à entrada do vinculador.Para adicionar essa biblioteca a sua entrada de vinculador no IDE, abra o menu de contexto do nó do projeto, escolha Propriedades e, em seguida, 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írgulas.Se seu projeto se vincula a bibliotecas estáticas que foram compiladas com uma versão do Visual Studio anterior a 2015, o vinculador pode relatar um símbolo externo não resolvido. Esses erros podem fazer referência a definições internas de
_iob
,_iob_func
ou importações relacionadas de determinadas funções<stdio.h>
na forma de imp. A Microsoft recomenda que você recompile todas as bibliotecas estáticas com a versão mais recente do compilador e das bibliotecas do C++ ao atualizar um projeto. Se a biblioteca é uma biblioteca de terceiros cuja fonte não está disponível, você deve solicitar ao terceiro um binário atualizado ou encapsular o uso dessa biblioteca em uma DLL separada que você compila com a versão mais antiga do compilador e das bibliotecas.Aviso
Se você estiver vinculando com SDK do Windows 8.1 ou anterior, você poderá se deparar com esses erros de símbolo externo não resolvido. Nesse caso, você deve resolver o erro adicionando a legacy_stdio_definitions.lib ao vinculador de entrada conforme descrito anteriormente.
Para solucionar problemas de erros de símbolo não resolvido, você pode tentar usar o
dumpbin.exe
para examinar os símbolos definidos em um binário. Experimente a seguinte linha de comando para exibir os símbolos definidos em uma biblioteca.dumpbin.exe /LINKERMEMBER somelibrary.lib
gets e _getws
As funções gets e _getws foram removidas. A função gets foi removida da Biblioteca do C Standard na C11 porque ela 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 para 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 para essas funções, considere o uso de _cgets_s e _cgetws_s.
Formatação de infinito e NaN
Nas versões anteriores, infinitos e NaNs eram formatados usando um conjunto de cadeias de caracteres de sentinela específico do MSVC.
Infinito: 1.#INF
NaN silencioso: 1.#QNAN
NaN sinalizado: 1.#SNAN
NaN indefinido: 1.#IND
Qualquer um desses formatos poderia ser prefixado por um sinal e poderia ser formatado de forma ligeiramente diferente, dependendo da largura do campo e da precisão (às vezes, com efeitos incomuns, por exemplo,
printf("%.2f\n", INFINITY)
imprimiria 1.#J porque o #INF seria "arredondado" com uma precisão de 2 dígitos). O C99 introduziu novos requisitos a respeito de como os infinitos e 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: inf
NaN silencioso: nan
NaN sinalizado: nan(snan)
NaN indefinido: nan(ind)
Todas podem ser prefixadas por um sinal. Se um especificador de formato maiúsculo for usado (%F, em vez de %f), as cadeias de caracteres serão impressas em letras maiúsculas (
INF
em vez deinf
), conforme necessário.As funções scanf foram modificadas para analisar essas novas cadeias de caracteres, portanto, essas cadeias de caracteres farão viagem de ida e volta entre
printf
escanf
.Formatação e análise de ponto flutuante
Novos algoritmos de formatação e análise de ponto flutuante foram introduzidos para melhorar a exatidão. Essa alteração afeta as famílias de funções printf e scanf,e funções como a strtod.
Os algoritmos de formatação antiga gerariam apenas um número limitado de dígitos e preencheriam as casas decimais restantes com zeros. Eles normalmente poderiam gerar cadeias de caracteres que fariam uma viagem de ida para o valor de ponto flutuante original, mas não eram ideais se você desejasse o valor exato (ou sua representação decimal mais próxima). Os novos algoritmos de formatação geram tantos dígitos quanto necessário para representar o valor (ou para preencher a precisão especificada). Como um exemplo do aperfeiçoamento, considere os resultados ao imprimir uma grande potência de dois:
printf("%.0f\n", pow(2.0, 80))
Saída antiga:
1208925819614629200000000
Nova saída:
1208925819614629174706176
Os algoritmos de análise antigos considerariam até 17 dígitos significativos da cadeia de entrada e descartariam o restante dos dígitos. Essa abordagem é suficiente para gerar uma aproximação do valor representado pela cadeia de caracteres e o resultado é normalmente muito próximo do resultado corretamente arredondado. A nova implementação considera todos os dígitos presentes e produz o resultado arredondado corretamente para todas as entradas (até 768 dígitos). Além disso, essas funções agora respeitam o modo de arredondamento (controlável por meio de fesetround). Essa é uma alteração de comportamento potencialmente significativa porque essas funções podem gerar resultados diferentes. Os novos resultados sempre são mais corretos 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 aquelas geradas pelos especificadores de formato printf %a e %A) e todas as cadeias de caracteres de infinito e NaN geradas pelas funções
printf
, conforme descrito acima.Preenchimento de zero %a e %A
Os especificadores de formato %a e %A formatam um número de ponto flutuante como uma mantissa hexadecimal e expoente binário. Nas versões anteriores, as funções
printf
preencheriam incorretamente as cadeias de caracteres com zero. Por exemplo,printf("%07.0a\n", 1.0)
imprimiria 00x1p+0, mas deveria imprimir 0x01p+0. Essa falha foi corrigida.Precisão %A e %a
A precisão padrão dos especificadores de formato %A e %a era de 6 nas versões anteriores da biblioteca. A precisão padrão agora é de 13 para conformidade com o Padrão C.
Essa é uma alteração de comportamento de runtime na saída de qualquer função que usa uma cadeia de caracteres de formato com %A ou %a. No comportamento antigo, a saída usando o especificador %A seria "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 da precisão.
Especificador %F
Agora há suporte para o especificador de formato/conversão %F. Ele é funcionalmente equivalente ao especificador de formato %f, exceto que os infinitos e NaNs são formatados usando letras maiúsculas.
Nas versões anteriores, a implementação costumava analisar F e N como modificadores de comprimento. Esse comportamento remonta à época dos espaços de endereçamento segmentado: esses modificadores de comprimento eram usados para indicar ponteiros distantes e próximos como em %Fp ou %Ns, respectivamente. Esse comportamento foi removido. Se %F for encontrado, será tratado como o especificador de formato %F; se %N for encontrado, será tratado como um parâmetro inválido.
Formatação de expoente
Os especificadores formato %e e %E formatam um número de ponto flutuante como uma mantissa e um expoente decimais. Os especificadores de formato %g e %G também formatam números nesse formato em alguns casos. Nas versões anteriores, o CRT sempre geraria cadeias de caracteres com expoentes de três dígitos. Por exemplo,
printf("%e\n", 1.0)
imprimiria 1.000000e+000, o que seria incorreto. o C exige que se o expoente é representável usando apenas um ou dois dígitos, apenas dois dígitos devem ser impressos.No Visual Studio 2005 foi adicionada uma opção de conformidade global: _set_output_format. Um programa poderia chamar essa função com o argumento _TWO_DIGIT_EXPONENT, para habilitar a impressão de expoente em conformidade. O comportamento padrão mudou para o modo de impressão expoente em conformidade com padrões.
Validação de cadeia de caracteres de formato
Nas versões anteriores, as funções
printf
escanf
aceitariam silenciosamente muitas cadeias de caracteres de formato inválido, às vezes, com efeitos incomuns. Por exemplo, %hlhlhld seria tratada como %d. Todas as cadeias de caracteres de formato inválidas são tratadas agora como parâmetros inválidos.Validação de cadeia de caracteres de modo fopen
Nas versões anteriores, a família de funções
fopen
aceitava silenciosamente algumas cadeias de caracteres de modo inválidas, tais comor+b+
. As cadeias de caracteres de modo inválidas agora são detectadas 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. Nas versões anteriores da biblioteca, tais fluxos poderiam ser relatados como sendo abertos em _O_WTEXT.
Essa é uma alteração significativa se seu código interpreta o modo _O_WTEXT para fluxos nos quais a codificação é UTF-8. Se seu aplicativo não oferece suporte a UTF_8, considere adicionar suporte para essa codificação cada vez mais comum.
snprintf e vsnprintf
As funções snprintf e vsnprintf agora estão implementadas. O código anterior geralmente fornecia definições de versões macro dessas funções porque elas não foram implementadas pela biblioteca CRT, mas elas não são mais necessárias nas versões mais recentes. Se snprintf ou vsnprintf forem definidas como uma macro antes de incluir
<stdio.h>
, a compilação falhará com um erro que indica o local em que a macro foi definida.Normalmente, a correção para esse problema é excluir todas as declarações de
snprintf
ouvsnprintf
no código do usuário.tmpnam gera nomes de arquivo utilizáveis
Nas versões anteriores, as funções
tmpnam
etmpnam_s
geravam nomes de arquivo na raiz da unidade (por exemplo, \sd3c.). Essas funções agora geram caminhos de nome de arquivo utilizáveis em um diretório temporário.Encapsulamento de FILE
Nas versões anteriores, o tipo FILE completo era definido publicamente em
<stdio.h>
, portanto, era possível que o código de usuário acessasse um FILE e modificasse seu conteúdo interno. A biblioteca foi alterada para ocultar os detalhes da implementação. Como parte dessa alteração, o FILE conforme definido em<stdio.h>
agora é um tipo opaco e seus membros estã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
strtof
ewcstof
falhavam ao definirerrno
como ERANGE quando o valor não era representável como um float. Esse erro era específico dessas duas funções; as funçõesstrtod
,wcstod
,strtold
ewcstold
não foram afetadas. Esse problema foi corrigido e é uma alteração da falha de runtime.Funções de alocação alinhada
Nas versões anteriores, as funções de alocação alinhada (
_aligned_malloc
,_aligned_offset_malloc
etc.) aceitariam silenciosamente as solicitações de um bloco com um alinhamento 0. O alinhamento solicitado deve ser uma potência de dois, que o zero não é. Um alinhamento solicitado de 0 agora é tratado como um parâmetro inválido. Esse problema foi corrigido e é uma alteração da falha de runtime.Funções heap
As funções
_heapadd
,_heapset
e_heapused
foram removidas. Essas funções não estão funcionando desde que o CRT foi atualizado para usar o heap do Windows.smallheap
A opção de link
smallheap
foi removida. Consulte Opções de link._stat
A família
_stat
de funções usaCreateFile
no Visual Studio 2015, em vez deFindFirstFile
como no Visual Studio 2013 e anterior. Isso significa que_stat
em um caminho que termina com uma barra terá êxito se o caminho se referir a um diretório, em vez de antes, quando a função cometesse um erro comerrno
definida comoENOENT
.
<string.h>
wcstok
A assinatura da função
wcstok
foi alterada para corresponder ao que é exigido pelo Padrão C. Nas versões anteriores da biblioteca a assinatura dessa função era:wchar_t* wcstok(wchar_t*, wchar_t const*)
Ela usava um contexto por thread interno para controlar o estado entre chamadas, 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.Foi adicionada uma nova função
_wcstok
com a assinatura antiga para facilitar a portabilidade. Ao compilar o código C++, também há uma sobrecarga embutida dewcstok
que tem a assinatura antiga. Essa sobrecarga é declarada como preterida. No código C, você pode definir _CRT_NON_CONFORMING_WCSTOK para fazer com que_wcstok
seja usada no lugar dewcstok
.
<time.h>
relógio
Nas versões anteriores, a função
clock
foi implementada usando a APIGetSystemTimeAsFileTime
do Windows. Com essa implementação, a função clock era sensível à hora do sistema e, portanto, não era necessariamente monotônica. A função clock foi reimplementada em termos deQueryPerformanceCounter
e agora é monotônica.fstat e _utime
Nas versões anteriores, as funções
_stat
,fstat
e_utime
lidavam com o horário de verão de maneira incorreta. Antes do Visual Studio 2013, todas essas funções ajustavam incorretamente as horas do horário padrão como se estivessem no horário de verão.No Visual Studio 2013, o problema foi corrigido na família de funções
_stat
, mas os problemas semelhantes não foram corrigidos nas famílias de funçõesfstat
e_utime
. Essa correção parcial resultou em problemas devido à inconsistência entre as funções. As famílias de funçõesfstat
e_utime
agora foram corrigidas, portanto todas essas funções agora lidam com o horário de verão de maneira correta e uniforme.asctime
Nas versões anteriores, a função
asctime
preencheria dias de dígito único 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 à esquerda, por exemplo,Fri Jun 6 08:00:00 2014
. Esse problema foi corrigido.strftime e wcsftime
As funções
strftime
ewcsftime
agora dão suporte aos especificadores de formato %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %u e %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 adequada de data e hora" para a localidade atual. Na localidade de C, essa representação deve ser o mesmo que
%a %b %e %T %Y
, o mesmo formato que é produzido porasctime
. Nas versões anteriores, o especificador de formato %c formatava horas incorretamente, usando uma representaçãoMM/DD/YY HH:MM:SS
. Esse problema foi corrigido.timespec e TIME_UTC
O cabeçalho
<time.h>
agora define o tipotimespec
e a funçãotimespec_get
do Padrão C11. Além disso, a macro TIME_UTC, para ser usada com a funçãotimespec_get
, agora está definida. Essa atualização é uma alteração da falha para o código que tem uma definição em conflito para qualquer um destes identificadores.CLOCKS_PER_SEC
A macro CLOCKS_PER_SEC agora se expande para um inteiro de tipo
clock_t
, conforme exigido pela linguagem C.
Biblioteca Padrão do C++
Para habilitar novas otimizações e verificações de depuração, a implementação da Biblioteca Padrão do C++ do Visual Studio desfaz intencionalmente a compatibilidade binária de uma versão para a próxima. Desse modo, quando a Biblioteca Padrão do C++ é usada, os arquivos de objeto e as bibliotecas estáticas que são compiladas usando versões diferentes não podem ser combinados em um binário (EXE ou DLL), e os objetos da Biblioteca Padrão do C++ não podem ser passados entre binários que são compilados usando versões diferentes. Tal combinação emite erros de vinculador sobre as incompatibilidades de _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 detectar mixagem de DLL e não pode detectar mixagem que envolva Visual Studio 2008 ou anterior.
Arquivos de inclusão da Biblioteca Padrão do C++
Algumas alterações foram feitas na estrutura de inclusão nos cabeçalhos da Biblioteca Padrão do C++. Os cabeçalhos da Biblioteca Padrão do C++ podem ser incluídos uns nos outros de formas não especificadas. Em geral, você deve escrever seu código para que ele inclua cuidadosamente todos os cabeçalhos que são necessários de acordo com o padrão C++ e não dependa de quais cabeçalhos da Biblioteca do C++ Standard inclui outros cabeçalhos de Biblioteca do C++ Standard. Isso torna o código portátil entre plataformas e versões. Pelo menos duas alterações de cabeçalho no Visual Studio 2015 afetam o código do usuário. Primeiro,
<string>
não inclui mais<iterator>
. Segundo,<tuple>
agora declarastd::array
sem incluir tudo de<array>
, o que pode interromper o código por meio da seguinte combinação de construções de código: o código tem uma variável chamada "array" e você tem uma diretiva de uso "using namespace std;" e você inclui um cabeçalho de Biblioteca Padrão do C++ (como<functional>
) que inclui<tuple>
, que agora declarastd::array
.steady_clock
A implementação
<chrono>
desteady_clock
foi alterada para atender aos requisitos Padrão do C++ para estabilidade e monotonicidade.steady_clock
agora se baseia emQueryPerformanceCounter
ehigh_resolution_clock
agora é um typedef parasteady_clock
. Como resultado, no Visual Studiosteady_clock::time_point
agora é uma typedef dechrono::time_point<steady_clock>
; no entanto, esse não é necessariamente o caso para outras implementações.Alocadores e const
Agora exigimos que as comparações de igualdade/desigualdade de alocador aceitem argumentos const em ambos os lados. Se os alocadores definem esses operadores conforme demonstrado a seguir,
bool operator==(const MyAlloc& other)
então você deve atualizá-los e declará-los como membros const:
bool operator==(const MyAlloc& other) const
Elementos const
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 falham ao compilar.std::allocator::deallocate
No Visual Studio 2013 e versões anteriores,
std::allocator::deallocate(p, n)
ignorava 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 deallocate
que retornava p. 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 em runtime.hash_map e hash_set
Os arquivos de cabeçalho não padrão
<hash_map>
e<hash_set>
estão preteridos no Visual Studio 2015 e serão removidos em uma versão futura. Em vez disso, use<unordered_map>
e<unordered_set>
.Comparadores e operador()
Os contêineres associativos (a família
<map>
) agora exigem que seus comparadores tenham operadores de chamada de função chamáveis por const. O código a seguir, em uma declaração de classe de comparador, agora falha ao 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) const
Características de tipo
Os nomes antigos para características de tipo de uma versão anterior do padrão de rascunho C++ foram removidos. Elas foram alteradas no C++11 e foram atualizadas para os valores de C++11 no Visual Studio 2015. A tabela a seguir mostra os nomes antigos e os novos.
Nome antigo Novo nome add_reference add_lvalue_reference has_default_constructor is_default_constructible has_copy_constructor is_copy_constructible has_move_constructor is_move_constructible has_nothrow_constructor is_nothrow_default_constructible has_nothrow_default_constructor is_nothrow_default_constructible has_nothrow_copy is_nothrow_copy_constructible has_nothrow_copy_constructor is_nothrow_copy_constructible has_nothrow_move_constructor is_nothrow_move_constructible has_nothrow_assign is_nothrow_copy_assignable has_nothrow_copy_assign is_nothrow_copy_assignable has_nothrow_move_assign is_nothrow_move_assignable has_trivial_constructor is_trivially_default_constructible has_trivial_default_constructor is_trivially_default_constructible has_trivial_copy is_trivially_copy_constructible has_trivial_move_constructor is_trivially_move_constructible has_trivial_assign is_trivially_copy_assignable has_trivial_move_assign is_trivially_move_assignable has_trivial_destructor is_trivially_destructible Políticas launch::any e launch::sync
As políticas
launch::any
elaunch::sync
não padrão foram removidas. Em vez disso, paralaunch::any
, uselaunch:async | launch:deferred
. Paralaunch::sync
, uselaunch::deferred
. Consulte Enumeração de inicialização.
MFC e ATL
MFC (Microsoft Foundation Classes)
não está mais incluído em uma instalação "Típica" do Visual Studio devido ao seu tamanho grande. Para instalar o MFC, escolha a opção de instalação Personalizada na configuração do Visual Studio 2015. Se já tiver o Visual Studio 2015 instalado, você 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 no Painel de Controle, de Programas e Recursos ou da mídia de instalação.
O Pacote Redistribuível do Visual C++ ainda inclui esta biblioteca.
Runtime de Simultaneidade
Macro Yield do Windows.h em conflito com concurrency::Context::Yield
O Runtime de Simultaneidade usava
#undef
anteriormente para excluir as definições da macro Yield para evitar conflitos entre a macro Yield definida no Windows.h e a funçãoconcurrency::Context::Yield
. Esta#undef
foi removida e uma nova chamada à API equivalente não conflitante concurrency::Context::YieldExecution foi adicionada. Para resolver conflitos com Yield, atualize seu código para chamar a funçãoYieldExecution
no lugar da Yield ou coloque o nome de funçãoYield
entre parênteses em sites de chamada, como no exemplo a seguir:(concurrency::Context::Yield)();
Aprimoramentos 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 devido aos aprimoramentos de conformidade feitos no Visual Studio 2015. Esses aprimoramentos não interrompem a compatibilidade binária de versões anteriores do Visual Studio, mas podem produzir erros de compilador em locais em que nunca houve erros anteriormente. Para obter mais informações, consulte Novidades no Visual C++ de 2003 até 2015.
Algumas vezes, os aprimoramentos contínuos no Visual Studio 2015 para conformidade do compilador podem alterar a maneira pela qual o compilador compreende seu código-fonte existente. Como resultado, você poderá encontrar erros novos ou diferentes durante o build ou até diferenças de comportamento no código que foi compilado anteriormente e parecia executar corretamente.
Felizmente, essas diferenças têm pouco ou nenhum impacto na maior parte 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 simples. Incluímos muitos exemplos de código-fonte que eram aceitáveis e que, talvez, precisem 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 build, elas não afetam a compatibilidade binária entre as atualizações de versões do Visual Studio. Uma alteração da falha é mais severa e pode afetar a compatibilidade binária, mas esses tipos de interrupções de compatibilidade binária ocorrem somente 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 significativas 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 do compilador
/Zc:forScope-
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 release
Essa opção foi comumente usada para permitir código não padrão que usa variáveis de loop após o momento em que deveriam ter saído do escopo, de acordo com o padrão. Ela só era necessária para compilar com a opção
/Za
, uma vez que sem/Za
, o uso de uma variável for loop após o final do loop sempre é permitido. Se a conformidade com os padrões não for importante nesse caso (por exemplo, se o código não se destinar à portabilidade para outros compiladores), você poderá desabilitar a opção/Za
(ou definir a propriedade Desabilitar extensões de linguagem como Não). Se você deseja escrever código portátil e em conformidade com os padrões, você deve reescrever o código, movendo a declaração de tais variáveis para um ponto fora do loop, para ficar em conformidade com o padrão.// 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 }
Opção do compilador
/Zg
A opção do compilador
/Zg
(Gerar Protótipos de Função) não está mais disponível. Essa opção do compilador foi anteriormente preterida.Não é possível executar testes de unidade com C++/CLI na linha de comando com mstest.exe. Em vez disso, use vstest.console.exe. Consulte Opções de linha de comando de VSTest.Console.exe.
palavra-chave mutable
O especificador de classe de armazenamento
mutable
não é mais permitido em locais em que anteriormente era compilado sem erros. Agora, o compilador gera um erro C2071 (classe de armazenamento inválida). Segundo o padrão, o especificadormutable
só pode ser aplicado a nomes de membros de dados de classe e não pode ser aplicado a nomes declarados const ou static e também não pode ser aplicado para fazer referência a membros.Por exemplo, considere o seguinte código:
struct S { mutable int &r; };
Versões anteriores do compilador aceitavam isso, mas agora o compilador retorna o seguinte erro:
error C2071: 'S::r': illegal storage class
Para corrigir o erro, remova a palavra-chave redundante
mutable
.char_16_t e char32_t
Você não pode mais usar
char16_t
nemchar32_t
como aliases em umtypedef
, porque esses tipos agora são tratados como internos. É comum que usuários e autores de biblioteca definamchar16_t
echar32_t
como aliases deuint16_t
euint32_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 o código, remova as declarações de
typedef
e renomeie todos os outros identificadores que estiverem em conflito com esses nomes.Parâmetros de modelo de não tipo
Alguns códigos que envolvem os parâmetros de modelo de não tipo agora têm a compatibilidade de tipo corretamente verificada quando você fornece argumentos de modelo explícitos. Por exemplo, o seguinte código compilado sem erros nas 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 corretamente apresentará um erro, porque o tipo de parâmetro de modelo não corresponde ao argumento de modelo (o parâmetro é um ponteiro para um membro const, mas a função f é não const):
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, verifique se o tipo do argumento de modelo que você usa corresponde ao tipo declarado do parâmetro do modelo.
__declspec(align)
O compilador não aceita mais
__declspec(align)
em funções. Esse constructo sempre foi ignorado, mas agora produz um erro do compilador.error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarations
Para corrigir esse problema, remova
__declspec(align)
da declaração da função. Uma vez que ela não tinha efeito, removê-la não altera nada.Manuseio de exceção
Há algumas alterações para o tratamento de exceções. Primeiro, os objetos de exceção precisam ser copiáveis ou móveis. O código a seguir era 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 é particular, portanto o objeto não pode ser copiado como acontece no curso normal de tratamento de exceção. O mesmo se aplica quando o construtor de cópia é declarado
explicit
.struct S { S(); explicit S(const S &); }; int main() { throw S(); // error }
Para atualizar seu código, verifique se o construtor de cópia do objeto de exceção
public
é público e não está marcado comoexplicit
.A captura de uma exceção pelo valor também exige que o objeto de exceção seja copiável. O código a seguir era 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 do
catch
para uma referência.catch (D& d) { }
Literais de cadeia de caracteres seguidos de macros
Agora o compilador dá suporte a literais definidos pelo usuário. Como consequência, os literais de cadeia de caracteres seguidos de macros sem qualquer espaço em branco de intervenção são interpretados como literais definidos pelo usuário, o que pode causar erros ou resultados inesperados. Por exemplo, nos compiladores anteriores o seguinte código foi compilado com êxito:
#define _x "there" char* func() { return "hello"_x; } int main() { char * p = func(); return 0; }
O compilador interpretou esse código como uma cadeia de caracteres literal "hello" seguida por uma macro, que é expandida em "there" e, em seguida, os dois literais de cadeia de caracteres foram concatenados em um. No Visual Studio 2015, o compilador interpreta essa sequência como um literal definido pelo usuário, mas como não há nenhum literal
_x
definido pelo usuário correspondente, ele gera 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 o literal de cadeia de caracteres e a macro.
Literais de cadeia de caracteres adjacentes
Assim como os anteriores, devido a alterações na análise de cadeia de caracteres, os literais de cadeia de caracteres adjacentes (literais de cadeia de caracteres largos ou estreitos) sem nenhum espaço em branco foram interpretados como uma única cadeia de caracteres concatenada nas versões anteriores do Visual C++. No Visual Studio 2015, agora você precisa adicionar um espaço em branco entre as duas cadeias de caracteres. Por exemplo, o código a seguir 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 de new e delete
Uma alteração foi feita no operador
delete
para colocá-lo em conformidade com o padrão C++14. Detalhes da alteração dos padrões podem ser encontrados em Desalocação dimensionada de C++. As alterações adicionam uma forma do operadordelete
global que usa um parâmetro de tamanho. A alteração da falha é que, se você já estava usando um operadordelete
com a mesma assinatura (para corresponder a um operador placement new), ocorre um erro do compilador (C2956, que ocorre no ponto em que placement new é usado, já que essa é a posição no código em que o compilador tenta identificar um operadordelete
correspondente apropriado).A função
void operator delete(void *, size_t)
era um operador placement delete correspondente à funçãovoid * operator new(size_t, size_t)
de placement new no C++11. Com a desalocação dimensionada de C++14, essa função delete agora é uma função de desalocação comum (operadordelete
global). O padrão indica que, se o uso de um placement new procurar uma função delete correspondente e localizar uma função de desalocação comum, o programa estará mal formado.Por exemplo, suponha que seu código defina um placement new e 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 de placement delete que você definiu e o novo operador
delete
de dimensionamento global. Considere se você pode usar um tipo diferente desize_t
para operadores de placement new edelete
. O tipo desize_t
typedef
depende do compilador; é umtypedef
paraunsigned int
em MSVC. Uma boa solução é usar um tipo enumerado como este:enum class my_type : size_t {};
Em seguida, altere sua definição de placement new e
delete
para usar 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 do valor inteiro) e atualizar a definição denew
edelete
para converter de volta para o tipo inteiro. Você não precisa usar umaenum
para isso. Um tipo de uma classe com um membrosize_t
também funciona.Uma solução alternativa é que você poderá eliminar completamente o placement new. Se seu código usar o placement new para implementar um pool de memória no qual o argumento de posicionamento é o tamanho do objeto que está sendo alocado ou excluído, o recurso de desalocação dimensionada poderá ser adequado para substituir seu próprio código de pool de memória personalizado e você poderá abandonar as funções de posicionamento e simplesmente usar seu próprio operador
delete
de dois argumentos em vez das funções de posicionamento.Se você não quiser atualizar o código imediatamente, reverta para o comportamento antigo usando a opção do compilador
/Zc:sizedDealloc-
. Se você usar essa opção, as funções delete de dois argumentos não existirão e não causarão conflito com o operador placement delete.Membros de dados de união
Membros de dados de uniões não podem mais ter tipos de referência. O código a seguir foi compilado com êxito no Visual Studio 2013, mas gera 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 type
Para resolver esse problema, altere os tipos de referência para um ponteiro ou um valor. Alterar o tipo para um ponteiro exige alterações no código que usa o campo de união. Alterar o código para um valor alteraria os dados armazenados na união, o que afeta outros campos, pois os campos nos tipos de união compartilham a mesma memória. Dependendo do tamanho do valor, ele também pode alterar o tamanho da união.
Uniões anônimas estão agora mais compatíveis com o padrão. As versões anteriores do compilador geravam um construtor e um destruidor explícitos de 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; // C2280
O 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>' here
Para resolver esse problema, forneça suas próprias definições do construtor e/ou do destruidor.
struct S { // Provide a default constructor by adding an empty function body. S() {} }; union { struct { S s; }; } u;
Uniões com structs anônimos
Para entrar em conformidade com o padrão, o comportamento do runtime foi alterado para membros de estruturas anônimas em uniões. O construtor para membros de estrutura anônima em uma união não é mais implicitamente chamado quando a união é criada. Além disso, o destruidor para membros de estrutura anônima em uma união não é mais implicitamente chamado quando a união sai do escopo. Considere o código a seguir, em que uma união U contém uma estrutura anônima que contém uma estrutura 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 da função f é limpa. Mas, no Visual Studio 2015, nem o construtor e nem o destruidor são chamados. O compilador dá um aviso sobre essa alteração de comportamento.
warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly called
Para restaurar o comportamento original, nomeie a estrutura anônima. O comportamento de runtime 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 adicionar chamadas para essas funções do construtor e do destruidor da 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 de modelo
Foram feitas alterações na resolução de nomes dos modelos. No C++, esse pode ser o caso de um ou mais nomes em consideração como correspondências possíveis causando uma instanciação de modelo inválida, ao considerar candidatos para a resolução de um nome. Essas instanciações inválidas normalmente não causam erros de compilador, um princípio que é conhecido como SFINAE (Substitution Failure Is Not An Error – Falha de substituição não é um erro).
Agora, se o SFINAE exige que o compilador instancie a especialização de um modelo de classe, os erros que ocorrem durante esse processo são erros de compilador. Nas versões anteriores, o compilador ignoraria esses 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ê obterá 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 de is_base_of, a classe
D
ainda não foi definida.Nesse caso, a correção é não usar essas características de tipo até que a classe seja definida. Se você mover as definições de
B
eD
para 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 dos arquivos de cabeçalho para certificar-se de que nenhuma definição de classe é compilada antes que os modelos problemáticos sejam usados.Construtores de cópia
No Visual Studio 2013 e Visual Studio 2015, o compilador gera um construtor de cópia para uma classe quando essa classe tem um construtor de movimento definido pelo usuário, mas nenhum construtor de cópia definido pelo usuário. No Dev14, esse construtor de cópia implicitamente gerado também é marcado "= delete".
principal declarado como "C" externo agora requer um tipo de retorno.
Agora, o código a seguir produz C4430.
extern "C" __cdecl main(){} // C4430
Para corrigir o erro, adicione o tipo de retorno:
extern "C" int __cdecl main(){} // OK
typename não é permitido em um inicializador de membro
Agora, o código a seguir 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
typename
do inicializador:S1() : T::type() // OK ...
A classe de armazenamento em 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
static_assert
sempre falhe:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations here
Para contornar esse problema, encapsule 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 here
Regras impostas para declarações de encaminhamento. (Aplica-se somente a C.)
Agora, o código a seguir produz C2065:
struct token_s; typedef int BOOL; typedef int INT; typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifier
Para corrigir esse problema, adicione as declarações de encaminhamento apropriadas:
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);
Imposição mais consistente de tipos de ponteiro de função
Agora, o código a seguir 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 a funções sobrecarregadas
Agora, o código a seguir 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 essa alteração for manifestada por meio de um identificador não declarado (C2065), poderá ser apropriado corrigir isso com uma declaraçãousing
.Esse padrão acontece frequentemente com ComPtr e com outros tipos no namespace
Microsoft::WRL
.Corrija o endereço incorreto de
Agora, o código a seguir produz C2440: '=': não é possí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()); }
O literal de cadeia de caracteres é uma matriz constante
Agora, o código a seguir produz 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*
, caso contrário, altere o corpo deh
para ter a aparência deste exemplo:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }
Cadeias de caracteres C++11 UDL
Agora, o código a seguir produz o erro C3688: sufixo de literal inválido 'L'; operador literal ou modelo de operador literal 'operator ""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,
MACRO
não é analisado como dois tokens (uma cadeia de caracteres seguida de uma macro). Agora, é analisado como um único UDL token. O mesmo se aplica a L""L"", que era analisado anteriormente como L"" e L"" e agora é analisado como L""L e "".As regras de concatenação de cadeia de caracteres 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 a concatenação de cadeias de caracteres com larguras de caracteres diferentes.
Caractere vazio C++11 removido
Agora, o código a seguir 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 de MFC não podem ser detectadas pelo valor porque não podem ser copiadas
O código a seguir em um aplicativo MFC agora causa o erro C2316: 'D': não pode ser detectado porque o destruidor e/ou o construtor de cópia está inacessível ou foi excluído
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 normalmente é usar as macros MFC TRY/CATCH.alignof
agora é uma palavra-chaveAgora, o código a seguir produz o erro C2332: 'class': nome de marca ausente. Para corrigir o código, você precisará renomear a classe ou, se a classe estiver executando o mesmo trabalho que
alignof
, basta substituir a classe pela palavra-chave nova.class alignof{}
constexpr
agora é uma palavra-chaveAgora, o código a seguir produz o erro C2059: erro de sintaxe: ')'. Para corrigir o código, você deve renomear qualquer função ou nomes de variáveis que são chamados de
constexpr
.int constexpr() {return 1;}
Tipos que podem ser movidos 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 excluídos
Agora, o código a seguir produz C2280 'S::S(S &&)': tentativa de fazer referência a uma função excluída:
struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = S(2, 3); //C2280
Para 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}; //OK
Conversão em ponteiro de função gerado somente quando não há nenhuma captura de 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
Agora, o código a seguir 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); }
Agora, o código a seguir 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 a inicialização de cópia inválida na inicialização de membro de dados não estáticos (NSDMI)
Agora, o código a seguir 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 };
Acesso aos construtores dentro de instruções decltype
Agora, o código a seguir produz C2248: 'S::S': não pode acessar o membro de acesso 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
S2
emS
:class S { S(); friend class S2; // Make S2 a friend public: int i; };
O construtor padrão de lambda é excluído implicitamente
Agora, o código a seguir 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 de que o construtor padrão seja chamado. Se o lambda não capturar nada, poderá ser convertido em um ponteiro de função.
Lambdas com um operador de atribuição excluída
Agora, o código a seguir 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.
Tentativa de mover um objeto com o construtor de cópia excluído
Agora, o código a seguir produz o erro C2280: 'moveable::moveable(const moveable &)': tentativa de 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::move
em vez disso:S(moveable && m) : m_m(std::move(m))
A classe local não pode fazer referência a outra classe local definida mais tarde na mesma função
Agora, o código a seguir produz o erro C2079: 's' usa undefined struct 'main::S2'
int main() { struct S2; struct S1 { void f() { S2 s; } }; struct S2 {}; }
Para corrigir o erro, mova a definição de
S2
para cima:int main() { struct S2 { //moved up }; struct S1 { void f() { S2 s; } }; }
Não é possível chamar um construtor base protegido no corpo do construtor derivado.
Agora, o código a seguir 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, em
S2
, remova a chamada paraS1()
do construtor e, se for necessário, coloque-o em outra função.{} impede a conversão em ponteiro
Agora, o código a seguir produz C2439 'S::p': não foi possível inicializar o membro
struct S { S() : p({ 0 }) {} void *p; };
Para corrigir o erro, remover as chaves em torno de 0. Caso contrário, use
0
ounullptr
, conforme mostrado neste exemplo:struct S { S() : p(nullptr) {} void *p; };
Definição de macro incorreta e uso com parênteses
Agora, o exemplo a seguir produz o 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: a função retorna a função:
#define DECLARE void f() struct S { DECLARE(); };
Para corrigir o erro, remova os parênteses após DECLARE em S:
DECLARE;
.O código a seguir gera o erro C2062: tipo 'int' inesperado
#define A (int) struct S { A a; };
Para corrigir o problema, defina
A
da seguinte forma:#define A int
Parênteses extras em declarações
O código a seguir gera o erro C2062: tipo 'int' inesperado
struct S { int i; (int)j; };
Para corrigir o erro, remova os parênteses em torno de
j
. Se os parênteses forem necessários para maior clareza, use umatypedef
.__Declspec(novtable) e construtores gerados pelo compilador
No Visual Studio 2015, há uma probabilidade maior de que construtores embutidos gerados pelo compilador de classes abstratas com classes base virtuais exponham o uso inapropriado de
__declspec(novtable)
quando usado em combinação com__declspec(dllimport)
.auto requer uma expressão única na inicialização de lista direta
Agora, o código a seguir produz o erro C3518: 'testPositions': em um contexto de inicialização de lista direta, o tipo 'auto' só pode ser deduzido de uma expressão de inicializador única
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
testPositions
da seguinte maneira: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} };
Verificar tipos versus ponteiros para tipos de is_convertible
Agora, o código a seguir 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
static_assert
para que ele compare os ponteiros paraD
eB2
:static_assert(std::is_convertible<D*, B2*>::value, "fail");
declarações de declspec(novtable) precisam ser consistentes
Declarações
__declspec
precisam ser consistentes em todas as bibliotecas. Agora, o código a seguir produzirá uma violação de regra de definição de um (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 particulares e herança indireta
As versões anteriores do compilador permitiam que uma classe derivada chamasse funções membro de suas classes base
private virtual
derivadas indiretamente. Esse comportamento antigo estava incorreto e não está em conformidade com o padrão C++. O compilador não aceita mais 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 function
Exemplo (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 new sobrecarregado e operador delete
Versões anteriores do compilador permitiam que o não membro operator new e o não membro operator delete fossem declarados como estáticos e fossem declarados em namespaces diferentes do namespace global. Esse comportamento antigo criava um risco do programa não chamar a implementação do operador
new
oudelete
pretendida pelo programador, resultando em comportamento silencioso de runtime incorreto. O compilador não aceita mais código escrito dessa maneira e, em vez disso, 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 C2323
Exemplo (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
new
embutido é considerado malformado.Chamar 'operator type()' (conversão definida pelo usuário) em tipos de não classe
As versões anteriores do compilador permitiam que o 'operator type()' fosse chamado em tipos de não classe ignorando-o silenciosamente. Esse comportamento antigo criava um risco de geração silenciosa de código incorreto, resultando em um comportamento imprevisível do runtime. O compilador não aceita mais código escrito dessa maneira e, em vez disso, emite o erro do compilador C2228.
error C2228: left of '.operator type' must have class/struct/union
Exemplo (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' }
Typename redundante em especificadores de tipo elaborados
As versões anteriores do compilador permitiam
typename
em especificadores de tipo elaborado, mas o código escrito dessa maneira é semanticamente incorreto. O compilador não aceita mais código escrito dessa maneira e, em vez disso, emite o erro do compilador C3406.error C3406: 'typename' cannot be used in an elaborated type specifier
Exemplo (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 ofereciam suporte à dedução de tipo de matrizes de uma lista de inicializadores. Agora o compilador oferece suporte a essa forma de dedução de tipo e, como resultado, as chamadas de modelos de função usando listas de inicializadores podem ser ambíguas ou pode ser escolhida uma sobrecarga diferente das versões anteriores do compilador. Para resolver esses problemas, o programa agora deve especificar explicitamente a sobrecarga pretendida pelo programador.
Quando esse novo comportamento faz com que a resolução de sobrecarga considere um candidato adicional que é igualmente tão bom quanto o candidato histórico, a chamada se torna ambígua e o compilador emite o erro do compilador C2668 como resultado.
error C2668: 'function' : ambiguous call to overloaded function.
Exemplo 1: chamada ambígua a 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 a 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 uma melhor correspondência que o candidato histórico, a chamada resolve-se, sem ambiguidade, no novo candidato, causando uma alteração 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 (depois)
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 de avisos de instrução switch
Uma versão anterior do compilador removeu alguns avisos relacionados a instruções
switch
. Esses avisos agora foram restaurados. Agora o compilador emite os avisos restaurados e os avisos relacionados a casos específicos (incluindo o caso padrão) são emitidos na linha que contém o caso com problema, em vez de na última linha da instrução switch. Como resultado da emissão desses avisos em linhas diferentes do que era no passado, os avisos que anteriormente eram suprimidos usando#pragma warning(disable:####)
não podem mais ser suprimidos como esperado. Para suprimir esses avisos conforme o esperado, talvez seja necessário mover a diretriz#pragma warning(disable:####)
para uma linha acima do primeiro caso problemático. A seguir estão os avisos restaurados:warning C4060: switch statement contains no 'case' or 'default' labels
warning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case label
warning C4062: enumerator 'bit1' in switch of enum 'flags' is not handled
warning 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' labels
warning 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 given
Exemplo 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 (depois)
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; } };
Os exemplos dos outros avisos restaurados são fornecidos em suas respectivas documentações.
#include: uso do especificador de diretório pai '..' em pathname (afeta somente
/Wall
/WX
)As versões anteriores do compilador não detectavam o uso do especificador '..' de diretório pai no nome do caminho de diretivas
#include
. O código escrito dessa maneira geralmente se destina a incluir cabeçalhos que existem fora do projeto usando caminhos relativos de projeto de forma incorreta. Esse comportamento antigo criava um risco de que o programa poderia ser compilado pela inclusão de um arquivo de origem diferente do pretendido pelo programador ou desses caminhos relativos não serem portáteis para outros ambientes de build. Agora o compilador detecta e notifica o programador do código escrito dessa maneira e emite um aviso do compilador C4464 opcional, caso esteja habilitado.warning C4464: relative include path contains '..'
Exemplo (antes)
#include "..\headers\C4426.h" // emits warning C4464
Exemplo (depois)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directories
Além disso, embora o compilador não forneça um diagnóstico específico, também é recomendável que o especificador ".." de diretório pai não seja usado para especificar diretórios de inclusão de seu projeto.
#pragma optimize() se estende além do fim do arquivo de cabeçalho (afeta somente
/Wall
/WX
)As versões anteriores do compilador não detectavam alterações nas configurações de sinalizador de otimização que escapam de um arquivo de cabeçalho incluído em uma unidade de tradução. Agora o compilador detecta e notifica o programador do código escrito dessa maneira e emite um aviso do compilador C4426 opcional no local do
#include
problemático, caso esteja habilitado. Esse aviso será emitido apenas se as alterações estiverem 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 C4426
Exemplo (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"
#pragma warning(push) e #pragma warning(pop) sem correspondência (afeta somente
/Wall
/WX
)As versões anteriores do compilador não detectavam a combinação de alterações de estado
#pragma warning(push)
com alterações de estado#pragma warning(pop)
em um arquivo de origem diferente, o que é raramente pretendido. Esse comportamento antigo criava um risco do programa ser compilado com um conjunto de avisos habilitados diferentes do que o programador pretendia, resultando, possivelmente, em comportamento silencioso de runtime incorreto. Agora o compilador detecta e notifica o programador do código escrito dessa maneira e emite um aviso do compilador C5031 opcional no local do#pragma warning(pop)
correspondente, caso esteja habilitado. Esse aviso inclui uma observação que faz referência ao local do #pragma warning(push) correspondente.warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different file
Exemplo (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, às vezes o código é escrito intencionalmente dessa maneira. O código escrito dessa maneira é sensível às alterações na ordem
#include
; quando possível, é recomendável que os arquivos de código-fonte gerenciem o estado de aviso de forma autocontida.#pragma warning(push) sem correspondência (afeta somente
/Wall
/WX
)As versões anteriores do compilador não detectavam alterações de estado
#pragma warning(push)
sem correspondência no final de uma unidade de tradução. O compilador agora detecta e notifica o programador sobre código escrito dessa maneira e emite um aviso C5032 opcional do compilador no local do#pragma warning(push)
sem correspondência, quando habilitado. Esse aviso será emitido somente 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.h
Exemplo (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 controle de estado de aviso #pragma aprimorado
As versões anteriores do compilador controlavam as alterações de estado de aviso #pragma de forma insuficientemente adequada para emitir todos os avisos pretendidos. Esse comportamento criava um risco de que certos avisos seriam efetivamente suprimidos em circunstâncias diferentes das que o programador pretendia. Agora o compilador acompanha o estado de
#pragma warning
de uma forma melhor, principalmente com relação às alterações de estado de#pragma warning
dentro de modelos e, opcionalmente, emite novos avisos C5031 e C5032 para ajudar o programador a localizar usos não intencionais de#pragma warning(push)
e#pragma warning(pop)
.Como resultado da melhoria do controle de alterações de estado de
#pragma warning
, os avisos que antes eram suprimidos incorretamente ou os avisos relacionados a problemas que eram mal diagnosticados agora podem ser emitidos.Identificação aprimorada de código inacessível
As alterações da Biblioteca Padrão do C++ e capacidade aprimorada para chamadas de função embutida em relação às versões anteriores do compilador podem permitir que o compilador comprove que determinado código está inacessível no momento. Esse novo comportamento pode resultar em emissões novas e mais frequentes de instâncias do aviso C4720.
warning C4720: unreachable code
Em muitos casos, esse aviso só pode ser emitido durante a compilação com otimizações habilitadas, já que as otimizações podem embutir mais chamadas de função, eliminar código redundante ou, caso contrário, possibilitar a determinação de que determinado código está inacessível. Observamos que as novas instâncias do aviso C4720 ocorreram frequentemente nos blocos try/catch, principalmente 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
Erros e avisos adicionais podem ser emitidos como resultado do suporte parcial à expressão SFINAE
As versões anteriores do compilador não analisavam determinados tipos de expressões dentro de especificadores
decltype
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++. Agora o compilador analisa essas expressões e tem suporte parcial à expressão SFINAE devido às melhorias contínuas de conformidade. Como resultado, o compilador emite avisos e erros encontrados nas expressões que as versões anteriores do compilador não analisavam.Quando esse novo comportamento analisa uma expressão
decltype
que inclui um tipo que ainda não foi declarado, o compilador emite o erro do compilador C2039 como resultado.error C2039: 'type': is not a member of 'global namespace'
Exemplo 1: uso 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
decltype
em que está faltando um uso necessário da palavra-chavetypename
para especificar que um nome dependente é um tipo, o compilador emite aviso do compilador C4346 junto com o erro do compilador C2923.warning C4346: 'S2<T>::Type': dependent name is not a type
error C2923: 's1': 'S2<T>::Type' is not a valid template type argument for parameter 'T'
Exemplo 2: o 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 (depois)
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> ())); };
volatile
variáveis de membro impedem construtores e operadores de atribuição implicitamente definidosAs versões anteriores do compilador permitiam que uma classe que tem variáveis de membro
volatile
tivesse construtores padrão copiar/mover e operadores de atribuição padrão copiar/mover gerados automaticamente. Esse comportamento antigo estava incorreto e não está em conformidade com o padrão C++. Agora, o compilador considera que uma classe que tem variáveis de membrovolatile
tenha operadores de construção e de atribuição não triviais que impedem que as implementações padrão desses operadores sejam geradas automaticamente. Quando essa classe for um membro de uma união (ou uma união anônima dentro de uma classe), os construtores copiar/mover e os operadores de atribuição copiar/mover da união (ou a classe que contém a união anônima) serão implicitamente definidos como excluídos. A tentativa de construir ou copiar a união (ou a classe que contém a união anônima) sem defini-la explicitamente é um erro e o compilador emite um erro de compilador C2280 como resultado.error C2280: 'B::B(const B &)': attempting to reference a deleted function
Exemplo (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 C2280
Exemplo (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 C2280
Funções de membro estático não dão suporte a qualificadores cv.
As versões anteriores do Visual Studio 2015 permitiam que funções de membro estático tivessem qualificadores cv. Esse comportamento era devido a uma regressão no Visual Studio 2015 e no Visual Studio 2015 Atualização 1. O Visual Studio 2013 e as versões anteriores do compilador rejeitam o código escrito dessa maneira. O comportamento do Visual Studio 2015 e do Visual Studio 2015 Atualização 1 está incorreto e não está em conformidade com o padrão C++. O Visual Studio 2015 Atualização 2 rejeita o código escrito dessa maneira e, em vez disso, emite o erro do 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 {} // C2511
Exemplo (depois)
struct A { static void func(); }; void A::func() {} // removed const
A declaração de encaminhamento de enum não é permitida no código do WinRT (afeta apenas
/ZW
)O código compilado para o WinRT (Windows Runtime) não permite que tipos
enum
sejam declarados de encaminhamento, da mesma forma que quando o código C++ gerenciado é compilado para o .NET Framework usando a opção de compilador/clr
. Esse comportamento garante que o tamanho de uma enumeração seja sempre conhecido e seja projetado corretamente para o sistema de tipos WinRT. O compilador rejeita o código escrito dessa maneira e emite um erro do compilador C2599 junto com o erro do compilador C3197.error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowed
error C3197: 'public': can only be used in definitions
Exemplo (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; } };
Operador new de não membro sobrecarregado e operador delete não podem ser declarados embutidos (Nível 1 (
/W1
) ativado por padrão)As versões anteriores do compilador não emitem um aviso quando o operador new de não membro e as funções do operador delete são declarados embutidos. O código escrito dessa maneira é malformado (não é necessário nenhum diagnóstico) e pode causar problemas de memória resultantes da falta de correspondência entre os operadores new e delete (principalmente quando usados em conjunto com desalocação dimensionada) que podem ser difíceis de diagnosticar. Agora o compilador emite o aviso do compilador C4595 para ajudar a identificar o código escrito dessa forma.
warning C4595: 'operator new': non-member operator new or delete functions may not be declared inline
Exemplo (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 de operador sejam retiradas de um arquivo de cabeçalho e movidas para um arquivo de origem correspondente.
Melhorias de conformidade na Atualização 3
std::is_convertable agora detecta a autoatribuição (biblioteca padrão)
As versões anteriores das característica de tipo
std::is_convertable
não detectavam corretamente a autoatribuição de um tipo de classe quando seu construtor de cópia era excluído ou particular. Agorastd::is_convertable<>::value
está definido corretamente comofalse
quando aplicado a um tipo de classe com um construtor de cópia particular ou excluído.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");
Nas versões anteriores do compilador, as asserções estáticas na parte inferior deste exemplo passam porque
std::is_convertable<>::value
foi definido incorretamente comotrue
. Agorastd::is_convertable<>::value
está definido corretamente comofalse
, fazendo com que as asserções estáticas falhem.Construtores triviais de cópia e movimentação padronizados ou excluídos respeitam especificadores de acesso
As versões anteriores do compilador não verificavam o especificador de acesso dos construtores triviais de cópia e movimentação padronizados ou excluídos antes de permitir que 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 incorreto, resultando em um comportamento imprevisível do runtime. Agora o compilador verifica o especificador de acesso dos construtores triviais de cópia e movimentação padrão ou excluídos para determinar se eles podem ser chamados e, caso não possam, emite um aviso do compilador C2248 como resultado.
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); }
Preterimento do suporte a código ATL atribuído (Nível 1 [
/W1
] ativado por padrão)As versões anteriores do compilador ofereciam suporte ao código ATL atribuído. Como um passo seguinte da remoção do suporte ao código ATL atribuído que começou no Visual Studio 2008, o código ATL atribuído foi preterido. Agora o compilador emite o aviso do compilador C4467 para ajudar a identificar esse tipo de código preterido.
warning C4467: Usage of ATL attributes is deprecated
Se você deseja continuar usando o código ATL atribuído até que o suporte seja removido do compilador, você pode desabilitar esse aviso passando os argumentos de linha de comando
/Wv:18
ou/wd:4467
para o compilador ou adicionando#pragma warning(disable:4467)
em 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 {};
Talvez você queira ou seja necessário 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 vc140.idl gerado pode ser usado para obter um arquivo *.idl que contém as interfaces e as anotações.
Em seguida, adicione uma etapa MIDL ao seu build para certificar-se de que as definições de interface de C++ são 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 a ATL diretamente no arquivo de implementação, como no código de exemplo abaixo.
Exemplo 2 Implementação (Depois)
#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 PCH (cabeçalho pré-compilado) e diretivas #include sem correspondência (afeta somente
/Wall
/WX
)As versões anteriores do compilador aceitavam diretivas
#include
incompatíveis em arquivos de origem entre compilações-Yc
e-Yu
ao usar arquivos de PCH (cabeçalho pré-compilado). O código escrito dessa maneira não é mais aceito pelo compilador. Agora o compilador emite o aviso do compilador CC4598 para ajudar a identificar diretivas#include
incompatíveis ao usar arquivos de PCH.warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that position
Exemplo (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 PCH (cabeçalho pré-compilado) e diretórios #include sem correspondência (afeta somente
/Wall
/WX
)As versões anteriores do compilador aceitavam argumentos de linha de comando de diretórios de inclusão incompatíveis (
-I
) para o compilador entre compilações-Yc
e-Yu
ao usar arquivos de PCH (cabeçalho pré-compilado). O código escrito dessa maneira não é mais aceito pelo compilador. Agora o compilador emite o aviso do compilador CC4599 para ajudar a identificar argumentos de linha de comando de diretórios de inclusão incompatíveis (-I
) ao usar arquivos de PCH.warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that position
Exemplo (antes)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cpp
Exemplo (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 no local em que ela seria 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, um erro não era emitido porque a chamada era
virtual
. No entanto, podia haver pane do programa no runtime. Agora, um erro de vinculador é emitido porque a classe é conhecida como final. Neste exemplo, para corrigir o erro, você faria um vínculo com o objeto que contém a definição deS2::f
.Ao usar funções friend em namespaces, você deve declarar novamente a função friend antes de fazer referência a ela ou um erro será obtido, pois o compilador agora está de acordo com o ISO C++ Standard. Por exemplo, esse código 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 esse código, declare a função
friend
: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 C++ Standard não permite a especialização explícita em uma classe. Embora o compilador do Microsoft C++ permita isso em alguns casos, em casos como no exemplo a seguir, um erro é gerado porque o compilador não considera a segunda função como sendo 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 esse código, modifique a segunda função:
template <> void f(char& val);
O compilador não tenta mais remover a ambiguidade das 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 esse 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 a ISO C++11, o código a seguir teria compilado e feito
x
resolver para o tipoint
:auto x = {0}; int y = x;
Este código agora resolve
x
para um tipo destd::initializer_list<int>
e causa um erro na próxima linha que tenta atribuirx
ao tipoint
. (Não há conversão por padrão.) Para corrigir esse código, useint
para substituirauto
:int x = {0}; int y = x;
A inicialização de agregação 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 ISO C++11 Standard exige inicialização uniforme para funcionar sem conversões redutoras. Antes, se uma conversão redutora estivesse disponível, um Aviso do Compilador (nível 4) C4242 seria emitido e não um erro.
int i = 0; char c = {i}; // error
Para corrigir esse código, adicione uma conversão de redução 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 qualquer uma destas formas:
void *p = 0; // or void *p = {0};
O nome da pesquisa foi alterada. O código a seguir é resolvido de forma diferente no compilador C++ no Visual Studio 2012 e no Visual Studio 2013:
enum class E1 { a }; enum class E2 { b }; int main() { typedef E2 E1; E1::b; }
No Visual Studio 2012, o
E1
na expressãoE1::b
é resolvido para::E1
no escopo global. No Visual Studio 2013,E1
na expressãoE1::b
é resolvido para a definiçãotypedef E2
emmain()
e tem o tipo::E2
.O layout do objeto foi alterado. No x64, o layout do objeto de uma classe pode ser alterado em relação às versões anteriores. Se tiver uma função
virtual
, mas não tiver uma classe base que tenha uma funçãovirtual
, o modelo de objeto do compilador inserirá um ponteiro em uma tabela de funçãovirtual
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 o x64 tentaria melhorar o layout para você, mas como ela falhou em funcionar corretamente em situações de código complexas, ela 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)
no x64 é 48, mas em versões anteriores, ele era avaliado como 32. Para fazer com que ele seja avaliado como 32 no compilador C++ no Visual Studio 2013 para x64, adicione uma classe base fictícia que tenha uma funçãovirtual
:__declspec(align(16)) struct S1 { }; struct dummy { virtual ~dummy() {} }; struct S2 : public dummy { virtual ~S2(); void *p; S1 s; };
Para encontrar locais no seu código que uma versão anterior tentou otimizar, use um compilador dessa versão juntamente com a opção de compilador
/W3
e 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': o layout da classe foi alterado de uma versão anterior do compilador devido a empacotamento melhor”.
O compilador x86 tem o mesmo problema de layout de qualidade inferior em todas as versões do compilador. Por exemplo, se este código foi compilado por x86:
struct S { virtual ~S(); int i; double d; };
O resultado de
sizeof(S)
será 24. No entanto, isso poderá 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 Padrão
O compilador C++ no Visual Studio 2013 detecta incompatibilidades em _ITERATOR_DEBUG_LEVEL, que foi implementado no Visual Studio 2010, bem como incompatibilidades de RuntimeLibrary. Essas incompatibilidades ocorrem quando as opções de compilador /MT
(versão estática), /MTd
(depuração estática), /MD
(versão dinâmica) e /MDd
(depuração dinâmica) são combinadas.
Se seu código reconhecer os modelos de alias simulados da versão anterior, você terá que alterá-lo. Por exemplo, em vez de
allocator_traits<A>::rebind_alloc<U>::other
, agora você precisa expressarallocator_traits<A>::rebind_alloc<U>
. Emboraratio_add<R1, R2>::type
agora não seja mais necessário e seja recomendado que você expliciteratio_add<R1, R2>
, o antigo ainda será compilado porque é obrigatório queratio<N, D>
tenha um "tipo" typedef para um índice reduzido, que será o mesmo tipo se já tiver sido reduzido.Você deve usar
#include <algorithm>
ao chamarstd::min()
oustd::max()
.Se o seu código existente usa enumerações com escopo simuladas da versão anterior – enumerações sem escopo tradicionais envolvidas em namespaces – será necessário alterá-lo. Por exemplo, se você fez referência ao tipo
std::future_status::future_status
, agora é preciso expressarstd::future_status
. No entanto, a maioria dos códigos não é afetada, por exemplo,std::future_status::ready
ainda é compilado.explicit operator bool()
é mais estrito que o operador unspecified-bool-type().explicit operator bool()
permite conversões explícitas para bool – por exemplo, dadoshared_ptr<X> sp
,static_cast<bool>(sp)
ebool b(sp)
são válidos – e "conversões contextuais" testáveis por booliano para bool – por exemplo,if (sp)
,!sp
,sp &&
. No entanto,explicit operator bool()
proíbe conversões implícitas para bool, portanto, você não pode expressarbool b = sp;
e, dado um tipo de retorno bool, você não pode expressarreturn sp
.Agora que os modelos reais variadic estão implementados, _VARIADIC_MAX e as macros relacionadas não têm efeito. Se você ainda estiver definindo _VARIADIC_MAX, ele será ignorado. Se você reconheceu a maquinaria da macro com suporte a modelos variadic simulados de qualquer outra maneira, será preciso modificar seu código.
Além de palavras-chave comuns, os cabeçalhos da Biblioteca do C++ Standard agora proíbem a substituição de macros das palavras-chave override e final sensíveis ao contexto.
reference_wrapper
,ref()
ecref()
agora proíbem a associação a objetos temporários.<random>
agora impõe rigidamente suas pré-condições de tempo de compilação.Diversas características de tipo da Biblioteca Padrão do C++ têm a pré-condição "T deve ser um tipo completo". Embora o compilador agora imponha isso de forma mais rígida, essa pré-condição não pode ser imposta em todas as situações. (Como as violações de pré-condição da Biblioteca Padrão do C++ disparam o comportamento indefinido, o Padrão não assegura a imposição.)
A Biblioteca do C++ Standard não dá suporte a
/clr:oldSyntax
.A especificação C++11 para
common_type<>
teve consequências inesperadas e indesejadas; em particular, fazcommon_type<int, int>::type
retornarint&&
. Portanto, o compilador implementa a resolução proposta para o problema 2141 do grupo de trabalho de biblioteca, que fazcommon_type<int, int="">::type
retornarint
.Como efeito colateral dessa alteração, o caso de identidade não funciona mais (
common_type<T>
nem sempre resulta no tipoT
). Esse comportamento está de acordo 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
std::identity
não padrão que seja definida em<type_traits>
porque ela não funcionará para<void>
. Em vez disso, implemente sua própria característica de tipo de identidade para atender às suas necessidades. Veja um exemplo:template < typename T> struct Identity { typedef T type; };
MFC e ATL
Somente Visual Studio 2013: a Biblioteca MFC MBCS não está incluída no Visual Studio porque o Unicode é muito popular e o uso de MBCS foi significativamente reduzido. Essa alteração também mantém o MFC alinhado de forma mais próxima ao próprio Windows SDK, uma vez que vários dos controles e mensagens novos são somente Unicode. No entanto, se você precisar continuar usando a Biblioteca MFC MBCS, poderá baixá-la no Centro de Download da Microsoft em Biblioteca MFC multibyte para Visual Studio 2013. O Pacote Redistribuível do Visual C++ 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 posteriores).
A acessibilidade para a faixa de opções do MFC foi alterada. 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 método
CDatabase::GetConnect
foi removido. Para melhorar a segurança, a cadeia de conexão agora é armazenada criptografada e é descriptografada somente quando necessário; ela não pode ser retornada como texto sem formatação. A cadeia de caracteres pode ser obtida usando o métodoCDatabase::Dump
.A assinatura de
CWnd::OnPowerBroadcast
foi alterada. A assinatura desse manipulador de mensagens foi alterada para obter 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::OnDisplayChange
foi alterado 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::OnDDEInitiate
foi alterado 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::OnDDEExecute
foi alterado para (CWnd*, HANDLE) em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_DDE_EXECUTE possa ser usada no mapa de mensagens.CFrameWnd::OnDDETerminate
foi alterado para (CWnd*) como o parâmetro, em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_DDE_TERMINATE possa ser usada no mapa de mensagens.CMFCMaskedEdit::OnCut
foi alterado para sem parâmetros em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_CUT possa ser usada no mapa de mensagens.CMFCMaskedEdit::OnClear
foi alterado para sem parâmetros em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_CLEAR possa ser usada no mapa de mensagens.CMFCMaskedEdit::OnPaste
foi alterado para sem parâmetros em vez de (WPARAM, LPARAM) para que a nova macro ON_WM_PASTE possa ser usada no mapa de mensagens.
As diretivas
#ifdef
nos arquivos de cabeçalho MFC foram removidas. Várias diretivas#ifdef
nos arquivos de cabeçalho MFC relacionados a versões sem suporte do Windows (WINVER < 0x0501
) foram removidas.ATL DLL (atl120.dll) foi removida. A ATL agora é fornecida como cabeçalhos e uma biblioteca estática (atls.lib).
Atlsd.lib, atlsn.lib e atlsnd.lib foram removidas. Atls.lib não tem dependências ou código de conjunto de caracteres que seja específico para a depuração/versão. Como ela funciona da mesma forma para Unicode/ANSI e depuração/versão, somente uma versão da biblioteca é necessária.
A ferramenta Rastreamento de ATL/MFC foi removida com a ATL DLL e o mecanismo de rastreamento foi simplificado. O construtor
CTraceCategory
agora usa um parâmetro (o nome da categoria) e as macros TRACE chamam as funções de relatório de depuração de CRT.
Alterações da falha do Visual Studio 2012
Compilador
A opção do compilador
/Yl
foi alterada. Por padrão, o compilador usa essa opção, o que pode levar a erros LNK2011 em determinadas condições. Para obter mais informações, consulte /Yl (Injetar referência de PCH para Biblioteca de Depuração).No código que é compilado usando
/clr
, a palavra-chave de classeenum
define uma enumeração de C++11 e não uma enumeração de CLR (Common Language Runtime). Para definir um enum de CLR, você deve ser explícito sobre sua acessibilidade.Use a palavra-chave do modelo para remover a ambiguidade explicitamente de um nome dependente (conformidade com o Padrão de Linguagem C++). No exemplo a seguir, a palavra-chave realçada do modelo é obrigatória para resolver a ambiguidade. Para obter mais informações, consulte Resolução de nomes de tipos dependentes.
template < typename X = "", typename = "" AY = ""> struct Container { typedef typename AY::template Rebind< X> ::Other AX; };
A expressão constante de 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
/GS
e que tenha uma vulnerabilidade off-by-one pode levar à finalização do processo em runtime, 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 terminate
A arquitetura padrão para compilações x86 é alterada para SSE2. Portanto, o compilador pode emitir instruções SSE e usará os registros XMM para executar cálculos de ponto flutuante. Se você quiser reverter para o comportamento anterior, use o sinalizador de compilador
/arch:IA32
para especificar a arquitetura como IA32.O compilador pode emitir avisos Aviso do Compilador (nível 4) C4703 e C4701 quando anteriormente não emitia. O compilador aplica verificações mais fortes para o uso de variáveis locais não inicializadas do tipo ponteiro.
Quando o novo sinalizador de vinculador
/HIGHENTROPYVA
é especificado, o Windows 8 geralmente faz com que as alocações de memória retornem um endereço de 64 bits. (Antes do Windows 8, essas alocações retornavam com mais frequência endereços com menos de 2 GB.) Essa alteração pode expor bugs de truncamento de ponteiro no código existente. Por padrão, essa opção está ativada. Para desabilitar esse comportamento, especifique/HIGHENTROPYVA:NO
.O compilador gerenciado (Visual Basic/C#) também dá suporte a
/HIGHENTROPYVA
para builds gerenciados. No entanto, nesse caso, a opção/HIGHENTROPYVAswitch
está desativada por padrão.
IDE
- Apesar de recomendarmos 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 de C++/CLI existentes. Se você tiver que criar um Aplicativo do Windows Forms ou qualquer outro aplicativo de interface do usuário do .NET, use o C# ou o Visual Basic. Usar o C++/CLI somente para fins de interoperabilidade.
Biblioteca de Padrões Paralelos e Biblioteca de Runtime de Simultaneidade
A enumeração SchedulerType
de UmsThreadDefault
foi preterida. A especificação de UmsThreadDefault
produz um aviso de preterido e mapeia internamente de volta para o ThreadScheduler
.
Biblioteca Padrão
Após uma alteração da falha entre os padrões C++98/03 e C++11, o uso de argumentos de modelo explícitos para chamar
make_pair()
– comomake_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 – comomake_pair(x, y)
. O fornecimento de argumentos de modelo explícitos anula a finalidade da função. Se precisar de controle preciso sobre o tipo resultante, usepair
em vez demake_pair
– comopair<short, short>(int1, int2)
.Outra mudança importante entre os padrões C++98/03 e C++11: quando A é implicitamente conversível para B e B é implicitamente conversível para C, mas A não é implicitamente conversível para C, C++98/03 e O Visual Studio 2010 permitiu que
pair<A, X>
fosse convertido (implícita ou explicitamente) empair<C, X>
. (O outro tipo, X, não interessa aqui e não é específico para o primeiro tipo do par.) O compilador C++ no Visual Studio 2012 detecta que A não é implicitamente conversível em C e remove o par conversão de resolução de sobrecarga. Essa é uma alteração positiva para muitos cenários. Por exemplo, sobrecarregarfunc(const pair<int, int>&)
efunc(const pair<string, string>&)
e chamarfunc()
compair<const char *, const char *>
compilará com essa alteração. No entanto, essa alteração interrompe o código que baseava-se em conversões de par agressivas. Esse código geralmente pode ser corrigido executando explicitamente uma parte da conversão – por exemplo, passandomake_pair(static_cast<B>(a), x)
para uma função que esperapair<C, X>
.O Visual Studio 2010 simulava modelos variadic – por exemplo,
make_shared<T>(arg1, arg2, argN)
– até o limite de 10 argumentos, marcando sobrecargas e especializações com o mecanismo do pré-processador. No Visual Studio 2012, esse limite é reduzido a 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 configurar o limite anterior definindo explicitamente _VARIADIC_MAX como 10 em todo o projeto.O C++11 17.6.4.3.1 [macro.names]/2 proíbe a substituição de palavras-chave por macros quando os cabeçalhos da Biblioteca do C++ Standard estão incluídos. Os cabeçalhos agora emitem erros do compilador se detectam palavras-chave substituídas por macros. (Definir _ALLOW_KEYWORD_MACROS permite que esse código seja compilado, mas desencorajamos fortemente esse uso.) Como exceção, a forma 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")
. A definição de _ENFORCE_BAN_OF_MACRO_NEW faz exatamente o que seu nome sugere.Para implementar várias otimizações e verificações de depuração, a implementação da Biblioteca Padrão do C++ interrompe intencionalmente a compatibilidade binária entre as versões do Visual Studio (2005, 2008, 2010, 2012). Quando a Biblioteca do C++ Standard é usada, isso proíbe a mistura de arquivos de objeto e das bibliotecas estáticas que são compiladas usando versões diferentes em um binário (EXE ou DLL) e proíbe a passagem dos objetos da Biblioteca do C++ Standard entre binários que são compilados usando versões diferentes. A mistura de arquivos-objetos e bibliotecas estáticas usando a Biblioteca Padrão do C++ que foi compilada usando o Visual Studio 2010 com aquelas que foram compiladas usando o compilador C++ no Visual Studio 2012, emite erros de vinculador sobre a incompatibilidade de _MSC_VER, em que _MSC_VER é a macro que contém a versão principal do compilador (1700 para o Visual C++ no Visual Studio 2012). Essa verificação não pode detectar a combinação de DLL e não pode detectar uma combinação que envolva 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 detecta incompatibilidades de Biblioteca em Runtime. Essas incompatibilidades ocorrem quando as opções de compilador
/MT
(versão estática),/MTd
(depuração estática),/MD
(versão dinâmica) e/MDd
(depuração dinâmica) são combinadas.operator<()
,operator>()
,operator<=()
eoperator>=()
estavam disponíveis anteriormente para as famílias de contêineresstd::unordered_map
estdext::hash_map
, embora suas implementações não fossem úteis. Esses operadores não padrão foram removidos do Visual C++ no Visual Studio 2012. Além disso, a implementação deoperator==()
eoperator!=()
para a famíliastd::unordered_map
foi estendida para cobrir a famíliastdext::hash_map
. (É recomendável que você evite o uso da famíliastdext::hash_map
no novo código.)C++11 22.4.1.4 [locale.codecvt] especifica que
codecvt::length()
ecodecvt::do_length()
devem usar parâmetrosstateT&
modificáveis, mas o Visual Studio 2010 usavaconst stateT&
. O compilador C++ no Visual Studio 2012 usastateT&
conforme designado pelo padrão. Essa diferença é significativa para qualquer pessoa que esteja tentando substituir a função virtualdo_length()
.
CRT
O heap do CRT (Runtime de C), que é usado para new e malloc(), não é mais particular. O CRT agora usa o heap do processo. Isso significa que o heap não será destruído quando uma DLL for descarregada, portanto as DLLs vinculadas estaticamente à CRT devem garantir que a memória alocada pelo código da DLL seja limpa antes de ser descarregada.
A função
iscsymf()
faz declarações com valores negativos.O struct
threadlocaleinfostruct
foi alterado para acomodar as alterações nas funções de localidade.As funções de CRT que têm intrínsecos correspondentes como
memxxx()
,strxxx()
foram removidas de intrin.h. Se você incluiu intrin.h apenas para essas funções, agora você deverá incluir os cabeçalhos de CRT correspondentes.
MFC e ATL
O suporte à Fusão (afxcomctl32.h) foi removido. Portanto, todos os métodos que foram definidos em
<afxcomctl32.h>
foram removidos. Os arquivos de cabeçalho<afxcomctl32.h>
e<afxcomctl32.inl>
foram excluídos.O nome de
CDockablePane::RemoveFromDefaultPaneDividier
foi alterado paraCDockablePane::RemoveFromDefaultPaneDivider
.A assinatura de
CFileDialog::SetDefExt
foi alterada para usar LPCTSTR. Portanto, os builds de Unicode foram afetados.As categorias de rastreamento de ATL obsoletas foram removidas.
A assinatura de
CBasePane::MoveWindow
foi alterada para usar umconst CRect
.A assinatura de
CMFCEditBrowseCtrl::EnableBrowseButton
foi alterada.m_fntTabs
em_fntTabsBold
removidos deCMFCBaseTabCtrl
.Foi adicionado um parâmetro aos construtores
CMFCRibbonStatusBarPane
. (É um parâmetro padrão e, portanto, não causa interrupção de código-fonte.)Foi adicionado um parâmetro ao construtor
CMFCRibbonCommandsListBox
. (É um parâmetro padrão e, portanto, não causa interrupção de código-fonte.)A API
AFXTrackMouse
foi removida (e o temporizador proc relacionado). Use a APITrackMouseEvent
do Win32 em vez disso.Foi adicionado um parâmetro ao construtor
CFolderPickerDialog
. (É um parâmetro padrão e, portanto, não causa interrupção de código-fonte.)O tamanho da estrutura
CFileStatus
foi alterado: o membrom_attribute
foi alterado de BYTE para DWORD (para corresponder ao valor retornado deGetFileAttributes
).CRichEditCtrl
eCRichEditView
usam MSFTEDIT_CLASS (controle RichEdit 4.1) em vez de RICHEDIT_CLASS (controle RichEdit 3.0) em builds de Unicode.AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground
foi removido porque é sempre TRUE no Windows Vista, Windows 7 e Windows 8.AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable
foi removido porque é sempre TRUE no Windows Vista, Windows 7 e Windows 8.AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea
foi removido. Chame a API do Windows diretamente no Windows Vista, Windows 7 e Windows 8.AFX_GLOBAL_DATA::DwmDefWindowProc
foi removido. Chame a API do Windows diretamente no Windows Vista, Windows 7 e Windows 8.AFX_GLOBAL_DATA::DwmIsCompositionEnabled
foi renomeado comoIsDwmCompositionEnabled
para eliminar a colisão de nomes.Os identificadores foram alterados para um número de temporizadores internos do MFC e as definições foram movidas para afxres.h (AFX_TIMER_ID_*).
A assinatura do método
OnExitSizeMove
foi alterada para concordar com a macro ON_WM_EXITSIZEMOVE:CFrameWndEx
CMDIFrameWndEx
CPaneFrameWnd
O nome e a assinatura de
OnDWMCompositionChanged
foram alterados para concordar com a macro ON_WM_DWMCOMPOSITIONCHANGED:CFrameWndEx
CMDIFrameWndEx
CPaneFrameWnd
A assinatura do método
OnMouseLeave
foi alterada para concordar com a macro ON_WM_MOUSELEAVE:CMFCCaptionBar
CMFCColorBar
CMFCHeaderCtrl
CMFCProperySheetListBox
CMFCRibbonBar
CMFCRibbonPanelMenuBar
CMFCRibbonRichEditCtrl
CMFCSpinButtonCtrl
CMFCToolBar
ReplaceThisTextCMFCToolBarComboBoxEdit
CMFCToolBarEditCtrl
CMFCAutoHideBar
A assinatura de
OnPowerBroadcast
foi alterada para concordar com a macro ON_WM_POWERBROADCAST:CFrameWndEx
CMDIFrameWndEx
A assinatura de
OnStyleChanged
foi alterada para concordar com a macro ON_WM_STYLECHANGED:CMFCListCtrl
CMFCStatusBar
O método interno
FontFamalyProcFonts
foi renomeado paraFontFamilyProcFonts
.Vários objetos globais estáticos
CString
foram removidos para eliminar perdas de memória em algumas situações (substituídos por #defines) e as seguintes variáveis de membro de classe:CKeyBoardManager::m_strDelimiter
CMFCPropertyGridProperty::m_strFormatChar
CMFCPropertyGridProperty::m_strFormatShort
CMFCPropertyGridProperty::m_strFormatLong
CMFCPropertyGridProperty::m_strFormatUShort
CMFCPropertyGridProperty::m_strFormatULong
CMFCPropertyGridProperty::m_strFormatFloat
CMFCPropertyGridProperty::m_strFormatDouble
CMFCToolBarImages::m_strPngResType
CMFCPropertyGridProperty::m_strFormat
A assinatura de
CKeyboardManager::ShowAllAccelerators
foi alterada e o parâmetro delimitador de acelerador foi removido.CPropertyPage::GetParentSheet
foi adicionado e, na classeCPropertyPage
, chame-o em vez de chamarGetParent
para obter a janela de folha pai correta, que pode ser uma janela pai ou avô paraCPropertyPage
. Você pode precisar alterar o código para chamarGetParentSheet
em vez deGetParent
.#pragma warning(push) desbalanceado foi corrigido em ATLBASE.H, que causava avisos sendo desabilitados incorretamente. Agora, esses avisos estão corretamente habilitados depois que ATLBASE.H foi analisado.
Métodos relacionados a D2D foram movidos de AFX_GLOBAL_DATA para _AFX_D2D_STATE:
GetDirectD2dFactory
GetWriteFactory
GetWICFactory
InitD2D
ReleaseD2DRefs
IsD2DInitialized
D2D1MakeRotateMatrix
Em vez de chamar, por exemplo,
afxGlobalData.IsD2DInitialized
, chameAfxGetD2DState->IsD2DInitialized
.
Arquivos ATL*.CPP obsoletos foram removidos da pasta \atlmfc\include\.
A inicialização
afxGlobalData
foi movida para sob demanda em vez de no momento da inicialização CRT, para atender aos requisitos deDLLMain
.O método
RemoveButtonByIndex
foi adicionado à classeCMFCOutlookBarPane
.CMFCCmdUsageCount::IsFreqeuntlyUsedCmd
foi corrigido paraIsFrequentlyUsedCmd
.Várias instâncias de
RestoreOriginalstate
foram corrigidas paraRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane)
.Métodos não utilizados foram removidos de
CDockablePane
:SetCaptionStyle
,IsDrawCaption
,IsHideDisabledButtons
,GetRecentSiblingPaneInfo
eCanAdjustLayout
.As variáveis de membro estático
m_bCaptionText
em_bHideDisabledButtons
foram removidas deCDockablePane
.Foi adicionado um método
DeleteString
de substituição paraCMFCFontComboBox
.Métodos não utilizados foram removidos de
CPane
:GetMinLength
eIsLastPaneOnLastRow
.CPane::GetDockSiteRow(CDockingPanesRow *)
renomeado paraCPane::SetDockSiteRow
.
Alterações da falha do Visual Studio 2010
Compilador
A palavra-chave
auto
tem um significado padrão novo. Como uso do antigo significado é raro, a maioria dos aplicativos não será afetada por essa alteração.A nova palavra-chave
static_assert
foi introduzida, o que causará um conflito de nome se já existir um identificador com esse nome no seu código.O suporte para a nova notação lambda exclui o suporte para a codificação de um GUID sem aspas em um atributo de UUID IDL.
O .NET Framework 4 apresenta 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 do compilador /EHa, que captura todas as outras exceções. Para capturar explicitamente uma exceção de estado corrompido, use instruções __try-__except. Ou aplique o atributo [HandledProcessCorruptedStateExceptions] para habilitar uma função para capturar 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 do compilador
/GS
revisada protege contra estouros de buffer de maneira mais abrangente do que nas versões anteriores. Essa versão pode inserir verificações de segurança adicionais na pilha que podem diminuir o desempenho. Use a nova palavra-chave__declspec(safebuffers)
para instruir o compilador a não inserir verificações de segurança para uma função específica.Se você compilar com as opções de compilador
/GL
(Otimização do Programa Inteiro) e/clr
(Compilação Common Language Runtime), a opção/GL
será ignorada. Essa alteração foi feita porque a combinação de opções do compilador fornecia poucos benefícios. Como resultado dessa alteração, o desempenho do build foi aprimorado.Por padrão, o suporte para trígrafos está desabilitado no Visual Studio 2010. Use a opção do compilador
/Zc:trigraphs
para habilitar o suporte a trígrafos. Um trígrafo consiste em dois pontos de interrogação consecutivos ("??") seguidos por um terceiro caractere exclusivo. O compilador substitui um trígrafo por um caractere de pontuação correspondente. Por exemplo, o compilador substitui o trígrafo??=
pelo caractere '#'. Use trígrafos em arquivos de origem de 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 oferece mais suporte à otimização para o Windows 98. A opção
/OPT
(Otimizações) produzirá um erro em tempo de compilação se você especificar/OPT:WIN98
ou/OPT:NOWIN98
.As opções do compilador padrão que são especificadas pelas propriedades de sistema de build RuntimeLibrary e DebugInformationFormat foram alteradas. Por padrão, essas propriedades de build são especificadas em projetos que são criados pelo Visual C++, versões 7.0 à 10.0. Se você migrar um projeto que foi criado pelo Visual C++ 6.0, considere se deve especificar um valor para essas propriedades.
No Visual Studio 2010, RuntimeLibrary = MultiThreaded (
/MD
) e DebugInformationFormat = ProgramDatabase (/Zi
). No Visual C++ 9.0, RuntimeLibrary = MultiThreaded (/MT
) e DebugInformationFormat = Desabilitado.
CLR
- Os compiladores Microsoft C# e Visual Basic agora podem produzir um não PIA (não assembly de interoperabilidade primário). Um assembly não PIA pode usar tipos COM sem a implantação do PIA (assembly de interoperabilidade primário) relevante. Ao consumir assemblies não PIA produzidos pelo Visual C# ou Visual Basic, você deve fazer referência ao assembly PIA no comando de compilação antes de referenciar qualquer assembly não PIA que usa a biblioteca.
Projetos do Visual Studio C++ e MSBuild
Os 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. O Visual Studio 2010 converte automaticamente os arquivos de projeto de versões anteriores do Visual Studio no novo formato de arquivo. Um projeto existente será afetado se depender da ferramenta de build anterior, VCBUILD.exe ou do sufixo de arquivo de projeto .vcproj.
Em versões anteriores, o Visual C++ oferecia suporte para a avaliação tardia de folhas de propriedades. Por exemplo, uma folha de propriedades pai poderia importar uma folha de propriedades filho e a pai poderia usar uma variável definida na filho para definir outras variáveis. Avaliação tardia habilitava a folha pai a usar a variável de filho antes mesmo que a folha de propriedades filho fosse importada. No Visual Studio 2010, uma variável de folha de projeto não pode ser usada antes de ser definida porque o MSBuild somente dá suporte à avaliação adiantada.
IDE
A caixa de diálogo de encerramento do aplicativo não termina mais um aplicativo. Em versões anteriores, quando a função
abort()
outerminate()
fechava o build de varejo de um aplicativo, a Biblioteca em tempo de execução de C exibia uma mensagem de encerramento do aplicativo em uma caixa de diálogo ou janela de console. A mensagem dizia, em parte, "Este aplicativo solicitou que o Runtime terminasse de maneira incomum. Entre em contato com a equipe de suporte ao aplicativo para obter mais informações." A mensagem de encerramento do aplicativo era redundante porque o Windows posteriormente exibiu o manipulador de encerramento atual, que geralmente era a caixa de diálogo Relatório de Erros do Windows (Dr. Watson) ou o depurador do Visual Studio. Do Visual Studio 2010 em diante, a Biblioteca em tempo de execução de C não exibe a mensagem. Além disso, o runtime impede que o aplicativo finalize antes do início de um depurador. Essa só é uma alteração da falha se você depende do comportamento anterior da mensagem de encerramento do aplicativo.Especificamente para o Visual Studio 2010, o IntelliSense não funciona para código ou atributos de 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 não 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. Essa é uma alteração da falha somente se você desenvolveu uma classe que também é chamada de "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.
Nas versões anteriores do Visual Studio, era possível recompilar as bibliotecas em tempo de execução. O Visual Studio 2010 não dá mais suporte ao build de suas próprias cópias de arquivos de biblioteca em tempo de execução de C.
Biblioteca Padrão
O cabeçalho
<iterator>
não é mais incluído automaticamente por muitos outros arquivos de cabeçalho. Em vez disso, inclua esse cabeçalho explicitamente se você precisar de suporte para os iteradores autônomos definidos no cabeçalho. Um projeto existente será afetado se depender da ferramenta de build anterior, VCBUILD.exe ou do sufixo de arquivo de projeto .vcproj.iterator.No cabeçalho
<algorithm>
, as funçõeschecked_*
eunchecked_*
são removidas. E, no cabeçalho<iterator>
>, a classechecked_iterator
foi removida e a classeunchecked_array_iterator
foi adicionada.O construtor
CComPtr::CComPtr(int)
foi removido. Esse construtor permitia que um objetoCComPtr
fosse construído por meio macro NULL, mas era desnecessário e permitia construções absurdas de inteiros diferentes de zero.Um
CComPtr
ainda pode ser construído de NULL, que é definido como 0, mas falhará se for construído de um valor inteiro diferente de 0 literal. Use onullptr
em vez disso.As seguintes funções de membro de
ctype
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í-la pela versão não segura correspondente:ctype::do_narrow
,ctype::do_widen
,ctype::narrow
,ctype::widen
.
Bibliotecas ATL, MFC e CRT
Foi removido o suporte para que os usuários compilem as bibliotecas CRT, MFC e ATL. Por exemplo, nenhum arquivo NMAKE apropriado é fornecido. No entanto, os usuários ainda terão 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á publicado em um Blog da Equipe do Visual C++.
O suporte ao MFC para IA64 foi removido. No entanto, ainda é fornecido suporte para CRT e ATL em IA64.
Os ordinais não são mais reutilizados em arquivos de definição de módulo (.def) do MFC. Essa alteração significa que os ordinais não serão diferentes entre as versões secundárias e a compatibilidade binária para service packs e versões de engenharia de correção rápida será aprimorada.
Uma função virtual nova foi adicionada à classe
CDocTemplate
. Essa nova função virtual é a Classe CDocTemplate. A versão anterior deOpenDocumentFile
tinha dois parâmetros. A nova versão tem três parâmetros. Para dar suporte ao gerenciador de reinicialização, qualquer classe derivada deCDocTemplate
deve implementar a versão que tem três parâmetros. O novo parâmetro ébAddToMRU
.
Macros e Variáveis de Ambiente
- Não há mais suporte para a variável de ambiente __MSVCRT_HEAP_SELECT. Essa variável de ambiente foi removida e não há substituta.
Referência do Microsoft Macro Assembler
- Várias diretivas foram removidas do compilador de referência Macro Assembler da Microsoft. As diretivas removidas são
.186
,.286
,.286P
,.287
,.8086
,.8087
e.NO87
.
Alterações da falha do Visual Studio 2008
Compilador
Não há mais suporte para as plataformas Windows 95, Windows 98, Windows ME e Windows NT. Esses sistemas operacionais foram removidos da lista de plataformas de destino.
O compilador não oferece mais suporte a vários atributos que foram diretamente associados com o Servidor ATL. Não há mais suporte para os seguintes atributos:
perf_counter
perf_object
perfmon
request_handler
soap_handler
soap_header
soap_method
nome_da_tag
Projetos do Visual Studio C++
Ao atualizar projetos de versões anteriores do Visual Studio, você talvez precise modificar as macros WINVER e _WIN32_WINNT para que elas sejam maiores ou iguais a 0x0500.
Do Visual Studio 2008 em diante, o assistente de novo projeto não tem uma opção para criar um projeto do SQL Server do 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 de API do Windows Winable.h foi removido. Inclua Winuser.h no lugar dele.
A biblioteca de API do Windows Rpcndr.lib foi removida. Vincule com rpcrt4.lib no lugar dela.
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 de API do Windows
GetVersion
ouGetVersionEx
em vez disso:_get_osplatform
_get_osver
_get_winmajor
_get_winminor
_get_winver
A sintaxe para Anotações SAL foi alterada. Para obter mais informações, consulte Anotações SAL.
O filtro de IEEE agora oferece suporte ao conjunto de instruções SSE 4.1. Para obter mais informações, consulte _fpieee_flt_fpieee_flt.
As Bibliotecas em tempo de execução de C que vêm com o Visual Studio não são mais dependentes da DLL de sistema msvcrt.dll.
Biblioteca Padrão
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 aplicativo agora declarará quando um iterador tenta incrementar ou decrementar além dos limites do contêiner subjacente.
A variável de membro c da pilha Class agora é declarada protegida. Anteriormente, essa variável de membro era declarada pública.
O comportamento de
money_get::do_get
foi alterado. Antes, ao analisar um valor monetário com mais dígitos de fração do que era chamado porfrac_digits
,do_get
costumava consumir todos eles. Agora,do_get
para a análise após consumir, no máximo, os caracteres defrac_digits
.
ATL
A ATL não pode ser compilada sem uma dependência de CRT. Em versões anteriores do Visual Studio, você poderia usar #define ATL_MIN_CRT para tornar um projeto ATL minimamente dependente de CRT. No Visual Studio 2008, todos os projetos ATL dependem minimamente de CRT, independentemente de ATL_MIN_CRT estar definido.
A base de código do servidor ATL foi lançada como um projeto de código-fonte compartilhado no CodePlex e não é instalado como parte do Visual Studio. As classes de codificação e decodificação de dados de funções atlenc.h e utilitários e as classes de atlutil.h e atlpath.h foram mantidas e agora fazem parte da biblioteca ATL. Vários arquivos associados ao servidor ATL não fazem mais parte do Visual Studio.
Algumas funções não estão mais incluídas na DLL. Elas ainda estão localizadas 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
A ATL não pode ser compilada sem uma dependência de CRT. Em versões anteriores do Visual Studio, você poderia usar
#define ATL_MIN_CRT
para tornar um projeto ATL minimamente dependente de CRT. No Visual Studio 2008, todos os projetos ATL dependem minimamente de CRT, independentemente de ATL_MIN_CRT estar definido.A base de código do servidor ATL foi lançada como um projeto de código-fonte compartilhado no CodePlex e não é instalado como parte do Visual Studio. As classes de codificação e decodificação de dados de funções atlenc.h e utilitários e as classes de atlutil.h e atlpath.h foram mantidas e agora fazem parte da biblioteca ATL. Vários arquivos associados ao servidor ATL não fazem mais parte do Visual Studio.
Algumas funções não estão mais incluídas na DLL. Elas ainda estão localizadas 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
Classe
CTime
: a classeCTime
agora aceita datas a partir de 1/1/1900 E.C. em vez de 1/1/1970 E.C.A ordem de tabulação dos controles em caixas de diálogo do MFC: a ordem de tabulação correta de vários controles em uma caixa de diálogo do MFC será afetada se um controle ActiveX MFC for inserido na ordem de tabulação. Essa alteração corrige esse problema.
Por exemplo, crie um aplicativo de caixa de diálogo do MFC que tem 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 seja após o controle ActiveX e depois em tab. Antes dessa alteração, o foco foi para o controle de edição seguindo o controle ActiveX em vez do próximo controle de edição na ordem de tabulação.
Classe
CFileDialog
: modelos personalizados da classeCFileDialog
não podem ser portados automaticamente para o Windows Vista. Eles ainda podem ser usados, mas não terão a funcionalidade adicional ou a aparência das caixas de diálogo do estilo Windows Vista.Classes
CWnd
eCFrameWnd
: oCWnd::GetMenuBarInfo
método foi removido.O método
CFrameWnd::GetMenuBarInfo
agora é um método não virtual. Para obter mais informações, consulte Função GetMenuBarInfo no SDK do Windows.Suporte para ISAPI do MFC: o MFC não dá mais suporte ao build de aplicativos com a ISAPI (interface ISAPI). Se você deseja criar um aplicativo ISAPI, chame diretamente as extensões ISAPI.
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 build para controles comuns do Windows Vista.
Alterações da falha do Visual Studio 2005
CRT
Muitas funções foram preteridas. Consulte Funções CRT preteridas.
Agora, muitas funções validam seus parâmetros, interrompendo a execução se determinados parâmetros forem inválidos. Essa validação pode interromper 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âmetro.
O valor do descritor de arquivo -2 agora é usado para indicar que
stdout
estderr
não estão disponíveis para a saída, como, por exemplo, em um aplicativo do Windows que não tem nenhuma janela de console. O valor usado anteriormente era -1. Para obter mais informações, consulte _fileno.As bibliotecas CRT de thread único, libc.lib e libcd.lib, foram removidas. Use as bibliotecas CRT com multithread. Não há mais suporte para o sinalizador do compilador
/ML
. Versões de não bloqueio de algumas funções foram adicionadas em casos em que a diferença de desempenho entre o código com multithread e o código de thread único era potencialmente significativa.A sobrecarga de pow, double pow(int, int), foi removida para melhor conformidade com o padrão.
O especificador de formato %n não é mais compatível por padrão em qualquer uma das famílias ou funções printf porque é inerentemente inseguro. Se %n for encontrado, o comportamento padrão será invocar o manipulador de parâmetro inválido. Para habilitar o suporte a %n, use
_set_printf_count_output
(consulte também_get_printf_count_output
).Agora,
sprintf
imprime o sinal negativo de um zero com sinal.swprintf
foi alterado para conformidade com o Padrão. Agora, ele exige um parâmetro de tamanho. A forma deswprintf
sem um parâmetro de tamanho foi preterida._set_security_error_handler
foi removido. Remova as chamadas a 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 seja definido).As funções
_spawn
,_wspawn
deixamerrno
inalterado com êxito, conforme especificado pelo C Standard.O RTC agora usa caracteres largos por padrão.
As funções de suporte de palavra de controle de ponto flutuante foram preteridas por aplicativos compilados com
/CLR
ou/CLR:PURE
. As funções afetadas são_clear87
,_clearfp
,_control87
,_controlfp
,_fpreset
,_status87
,_statusfp
. Você pode desabilitar o aviso de substituição ao definir _CRT_MANAGED_FP_NO_DEPRECATE, mas o uso dessas funções em código gerenciado é imprevisível e não tem suporte.Agora, algumas funções retornam ponteiros const. O comportamento antigo não const pode ser restabelecido definindo _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 de Curinga.
Biblioteca Padrão (2005)
A classe de exceção (localizada no cabeçalho
<exception>
) foi movida para o namespacestd
. Nas versões anteriores, esta classe estava no namespace global. Para resolver os erros indicando que a classe de exceção não pode ser encontrada, adicione a seguinte instrução de uso seu código:using namespace std;
Ao chamar
valarray::resize()
, o conteúdo devalarray
será perdido e será substituído por valores padrão. O métodoresize()
é destinado para reinicializar ovalarray
em vez de aumentá-lo dinamicamente como um vetor.Iteradores de depuração: aplicativos criados com uma versão de depuração da Biblioteca em runtime de C e que usam iteradores de maneira incorreta, podem começar a ver declarações em runtime. Para desabilitar essas declarações, você deve definir _HAS_ITERATOR_DEBUGGING (substituída por
_ITERATOR_DEBUG_LEVEL
após o Visual Studio 2010) como 0. Para obter mais informações, consulte Suporte a iterador de depuração
Alterações significativas do Visual C++ .NET 2003
Compilador
O parênteses de fechamento agora é necessário de acordo com a diretiva definida de pré-processador (C2004).
As especializações explícitas não encontram mais os parâmetros de modelo do modelo primário (Erro do 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 (n) é um membro (Erro do Compilador C2247).
Verificações de acessibilidade aprimoradas no compilador agora detectam classes base inacessíveis (Erro do Compilador C2248).
Uma exceção não poderá ser capturada se o destruidor e/ou construtor de cópia estiver inacessível (C2316).
Os argumentos padrão em ponteiros para funções não são mais permitidos (Erro do Compilador C2383).
Um membro de dados estático não pode ser inicializado via classe derivada (Erro do Compilador C2477).
A inicialização de um
typedef
não é permitida pelo padrão e agora gera um erro do compilador (Erro do compilador C2513).bool
agora é um tipo adequado (Erro do Compilador C2632).Um UDC agora pode criar ambiguidade com operadores sobrecarregados (C2666).
Mais expressões agora são consideradas constantes de ponteiro nulo válido (Erro do Compilador C2668).
template<> agora é necessário em locais onde o compilador o implicaria anteriormente (Erro do compilador C2768).
A especialização explícita de uma função de membro fora da classe não será válida se a função já tiver sido especializada explicitamente por meio de uma especialização de classe de modelo (Erro do Compilador C2910).
Parâmetros de modelo de não tipo de ponto flutuante não são mais permitidos (Erro do Compilador C2993).
Modelos de classe não são permitidos como argumentos de tipo de modelo (C3206).
Nomes de função friend não são mais apresentados em namespace que o contenha (Erro do Compilador C3767).
O compilador não aceitará mais vírgulas adicionais em uma macro (C4002).
Um objeto de tipo POD construído com um inicializador da forma () será inicializado de modo 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).
Membros de dados estáticos não podem ser inicializados via 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).