Breaking Changes in the Visual C++ 2005 Compiler
This topic discusses the behavior changes in Visual C++ 2005 that can cause code that worked in a previous release to either not compile, or to behave differently at run time.
For more information on new features, see Changes in Visual C++ 2005 and Earlier Editions, Changes in the Visual C++ 2005 Libraries, and Changes in Visual C++ 2005 Compiler, Language, and Tools.
- Pointer-to-members now require qualified name and &
Code written for previous versions of the compiler that just used the method name will now give Compiler Error C3867 or Compiler Warning C4867. This diagnostic is required by Standard C++. Now, to create a pointer to a member function, the address of operator (&) must be used with the fully qualified name of the method. Not having to use the & operator and the fully qualified name of the method can lead to logic bugs in code due missing parentheses in function calls. Using the function's name without an argument list results in a function pointer which is convertible to several types. This code would have compiled, leading to unexpected behavior at runtime.
- Class must be accessible to a friend declaration
Visual C++ compilers prior to Visual C++ 2005 allowed a friend declaration to a class that was not accessible in the scope of the class containing the declaration. Now, the compiler will give Compiler Error C2248. To resolve this error, change the accessibility of the class specified in the friend declaration. This change was made to comply with the C++ standard.
- __int asm 3 now compiles to native
When compiled with /clr, __asm int 3 did not cause native code to be generated; the compiler translated the instruction to a CLR break instruction. In Visual C++ 2005, __asm int 3 now results in native code generation for the function. If you want a function to cause a break point in your code and if you want that function compiled to MSIL, use __debugbreak. For more information, see __asm and /clr (Common Language Runtime Compilation). This change was made to be more deterministic about when to generate native code versus managed code; inline assembly code should generate native code.
- Explicit specialization not allowed as a copy constructor/copy assignment operator
Code that depends on an explicit template specialization for a copy constructor or copy assignment operator will now get Compiler Error C2299. Standard C++ prohibits this. This change was made for conformance reasons, to make code more portable.
- Unspecialized class template can't be used as a template argument in a base class list
Using an unspecialized template class name in the base class list for a class definition will result in Compiler Error C3203. It is illegal to use an unspecialized template class name as a template parameter in a base class list. Explicitly add the template type parameters to the template class name when using it as a template parameter in a base class list. This change was made for conformance reasons, to make code more portable.
- A using declaration of nested type no longer allowed
Code that has a using declaration to a nested type will now generate Compiler Error C2885. To resolve fully qualify references to nested types, put the type in a namespace, or create a typedef. This change was made for conformance reasons, to make code more portable.
- Compiler does not allow const_cast to down cast under /clr:oldSyntax
Prior to Visual C++ 2005 the Visual C++ compiler allowed the const_cast Operator to down cast when compiling source code that uses Managed Extensions for C++ syntax. Performing a down cast with const_cast now results in Compiler Error C2440. To resolve, use the correct cast operator (for more information, see Casting Operators). This change was made for conformance reasons.
- Compiler disallows forward declaration of a managed enum
Prior to Visual C++ 2005 the Visual C++ compiler allowed forward declarations of managed enums. Now, declaring and not defining a managed enum when compiling with any form of /clr will result in Compiler Error C2599. To resolve, always define managed enums at declaration. This change was made because forward declarations of managed enums were not always guaranteed to work correctly: the compiler cannot correctly identify the underlying type of the enum. Also the C++ Standard does not allow enum declarations.
- /YX compiler option is removed
/YX generated automatic pre-compiled headers support. It was used by default from the development environment. If you remove /YX from your build configurations and replace it with nothing, it can result in faster builds. In addition to the possibility of unexpected behavior with /YX, it is preferable to use /Yc (Create Precompiled Header File) and /Yu (Use Precompiled Header File), which give you more control on how precompiled headers are used.
- /Oa and /Ow compiler options are removed
- /Op compiler option is removed
/Op compiler option had been removed. Use /fp (Specify Floating-Point Behavior) instead.
- /ML and /MLd compiler options have been removed
Visual C++ no longer supports single-threaded, statically linked CRT library support. Use /MT and /MTd instead. See C Run-Time Libraries for more information.
- /G3, /G4, /G5, /G6, /G7, and /GB compiler options have been removed
The compiler now uses a blended model that attempts to create the best output file for all architectures.
- /Gf has been removed
Use /GF (Eliminate Duplicate Strings) instead. /GF puts pooled strings into a read-only section, which is safer than the writeable section, where /Gf added them.
- /clr is not compatible with /MT
There is no support in the C Runtime Library to statically link to a managed application. All managed applications have to be dynamically linked (/MD). For more information on restrictions on using /clr, see /clr Restrictions.
- /GS is now on by default
Buffer overflow checking is now on by default. You can turn buffer overrun checking off with /GS-. See /GS (Buffer Security Check) for more information.
- /Zc:wchar_t now on by default
This is Standard C++ behavior; a wchar_t variable will default to the built in type instead of a short unsigned integer. This change will break binary compatibility when client code is linked with libraries that were compiled without /Zc:wchar_t (LNK2019). In that case, use /Zc:wchar_t- to revert to the old, non-standard behavior. This change was introduced to create conformant code by default.
For more information, see /Zc:wchar_t (wchar_t Is Native Type).
- /Zc:forScope now on by default
This is Standard C++ behavior; code that depends on the use of a variable declared in a for loop after the for loop scope has ended will now fail to compile. Use /Zc:forScope- to revert to the old, non-standard behavior. This change was introduced to create conformant code by default.
For more information, see /Zc:forScope (Force Conformance in for Loop Scope).
- Enforce parameter checking for Visual C++ attributes
Code that passes named attributes to the attribute constructor in quotes when the type is not a string and without quotes when the type is a string will now give Compiler Error C2065 or Compiler Warning (level 1) C4581. Previously all compiler attributes were parsed as strings, and if needed, the compiler inserted the missing quotes. Attribute support was enhanced by adding parameter checking validation. This will prevent unexpected behavior due to incorrect arguments to an attribute constructor.
For this release you cannot have a multi-byte character string (MBCS) in any argument to an attribute which takes an implicit string as an argument, even if the string is quoted (doing so can result in a corrupt .idl file). The workaround is as follows:
#define ARG string_with_MBCS_chars [helpstring(ARG)]
- Compiler now requires same template specification for multiple declarations of the same type.
If you have a forward declaration of a type so that you can create friends to that type, for example, the template specification of the type must be the same on all declarations for the type. Otherwise, the compiler will issue Compiler Error C2990.
- uuid attribute can no longer target managed types
- Syntax change for passing managed arrays to custom attributes
The type of the array is no longer deduced from the aggregate initialization list. The compiler now requires you to specify the type of the array as well as the initializer list. The old syntax will now result in Compiler Error C3104. This change was required because the compiler could not always correctly deduce the array type from the aggregate initialization list.
- Compiler will not inject int as the default type in declarations
Code that is missing the type in a declaration will no longer default to type int the compiler will generate Compiler Warning C4430 or Compiler Warning (level 4) C4431. Standard C++ does not support a default int and this change will ensure that you get the type you really want.
- dynamic_cast has enhanced conformance to the C++ standard.
The C runtime library now does a dynamic_cast runtime check to ensure the compile-time type of the expression being cast refers to a public base class sub-object of either the cast target type (for down-cast) or most-derived object type (for cross-cast). For more information, see Breaking Changes in dynamic_cast.
- An rvalue cannot be bound to a non-const reference.
An rvalue cannot be bound to a non-const reference. In previous versions of Visual C++, it was possible to bind an rvalue to a non-const reference in a direct initialization. This code now generates Compiler Warning (level 1) C4350.
- Value types no longer have a default constructor emitted, this can cause type initializers to run at different points
Prior to Visual C++ 2005 static constructors (type initializers) in value types were run when an instance of the value type was created. To ensure that static constructors are run, access a static data member or (/clr:oldSyntax only) define an instance constructor. Not providing a default constructor for value types was done because the common language runtime does not guarantee it will always call a default constructor. Also, not providing a default constructor for value types improves performance.
- Boxed value types are now read only in verifiable (/clr:safe) contexts.
The common language runtime no longer allows modifying a boxed value type when compiling a verifiable assembly. The compiler now gives Compiler Warning C4972 when this is detected.
C4792 is only given if you change the value of the underlying value object via boxed value object. The error will not occur if you change a copy of the value object (for example, changing a boxed object)
- Native types are private by default outside the assembly
Native types now will not be visible outside the assembly by default. For more information on type visibility outside the assembly, see Type Visibility. This change was primarily driven by the needs of developers using other, case-insensitive languages, when referencing metadata authored in Visual C++.
- /clr now accepts new CLR syntax for Visual C++
Prior to Visual C++ 2005, /clr compiled Managed Extensions for C++ syntax. /clr now compiles the new CLR syntax and ./clr:oldSyntax compiles Managed Extensions for C++ syntax. For more information on /clr, see /clr (Common Language Runtime Compilation). For more information on the new syntax, see Language Features for Targeting the CLR.
- /clr no longer compiles C source code files
Prior to Visual C++ 2005, you could compile C source code files with /clr, however this will now result in Command-Line Error D8045. To resolve, change the file extension to .cpp or .cxx, or compile with /TP or /Tp. See /Tc, /Tp, /TC, /TP (Specify Source File Type) for more information.
- MSIL changes when testing for equality
See How to: Test for Equality (C++/CLI) for more information.