Microsoft C++ Documentation
Microsoft C++ Documentation
Microsoft C++ Documentation
This reference explains the C++ programming language as implemented in the Microsoft C++ compiler. The
organization is based on The Annotated C++ Reference Manual by Margaret Ellis and Bjarne Stroustrup and on
the ANSI/ISO C++ International Standard (ISO/IEC FDIS 14882). Microsoft-specific implementations of C++
language features are included.
For an overview of Modern C++ programming practices, see Welcome Back to C++.
See the following tables to quickly find a keyword or operator:
C++ Keywords
C++ Operators
In This Section
Lexical Conventions
Fundamental lexical elements of a C++ program: tokens, comments, operators, keywords, punctuators, literals.
Also, file translation, operator precedence/associativity.
Basic Concepts
Scope, linkage, program startup and termination, storage classes, and types.
Built-in types The fundamental types that are built into the C++ compiler and their value ranges.
Standard Conversions
Type conversions between built-in types. Also, arithmetic conversions and conversions among pointer, reference,
and pointer-to-member types.
Declarations and definitions Declaring and defining variables, types and functions.
Operators, Precedence and Associativity
The operators in C++.
Expressions
Types of expressions, semantics of expressions, reference topics on operators, casting and casting operators,
run-time type information.
Lambda Expressions
A programming technique that implicitly defines a function object class and constructs a function object of that
class type.
Statements
Expression, null, compound, selection, iteration, jump, and declaration statements.
Classes and structs
Introduction to classes, structures, and unions. Also, member functions, special member functions, data
members, bit fields, this pointer, nested classes.
Unions
User-defined types in which all members share the same memory location.
Derived Classes
Single and multiple inheritance, virtual functions, multiple base classes, abstract classes, scope rules. Also,
the __super and __interface keywords.
Member-Access Control
Controlling access to class members: public , private , and protected keywords. Friend functions and classes.
Overloading
Overloaded operators, rules for operator overloading.
Exception Handling
C++ exception handling, structured exception handling (SEH), keywords used in writing exception handling
statements.
Assertion and User-Supplied Messages
#error directive, the static_assert keyword, the assert macro.
Templates
Template specifications, function templates, class templates, typename keyword, templates vs. macros, templates
and smart pointers.
Event Handling
Declaring events and event handlers.
Microsoft-Specific Modifiers
Modifiers specific to Microsoft C++. Memory addressing, calling conventions, naked functions, extended
storage-class attributes ( __declspec ), __w64 .
Inline Assembler
Using assembly language and C++ in __asm blocks.
Compiler COM Support
A reference to Microsoft-specific classes and global functions used to support COM types.
Microsoft Extensions
Microsoft extensions to C++.
Nonstandard Behavior
Information about nonstandard behavior of the Microsoft C++ compiler.
Welcome Back to C++
An overview of modern C++ programming practices for writing safe, correct and efficient programs.
Related Sections
Component Extensions for Runtime Platforms
Reference material on using the Microsoft C++ compiler to target .NET.
C/C++ Building Reference
Compiler options, linker options, and other build tools.
C/C++ Preprocessor Reference
Reference material on pragmas, preprocessor directives, predefined macros, and the preprocessor.
Visual C++ Libraries
A list of links to the reference start pages for the various Microsoft C++ libraries.
See also
C Language Reference
Welcome back to C++ - Modern C++
6/23/2021 • 8 minutes to read • Edit Online
Since its creation, C++ has become one of the most widely used programming languages in the world. Well-
written C++ programs are fast and efficient. The language is more flexible than other languages: It can work at
the highest levels of abstraction, and down at the level of the silicon. C++ supplies highly optimized standard
libraries. It enables access to low-level hardware features, to maximize speed and minimize memory
requirements. Using C++, you can create a wide range of apps. Games, device drivers, and high-performance
scientific software. Embedded programs. Windows client apps. Even libraries and compilers for other
programming languages get written in C++.
One of the original requirements for C++ was backward compatibility with the C language. As a result, C++ has
always permitted C-style programming, with raw pointers, arrays, null-terminated character strings, and other
features. They may enable great performance, but can also spawn bugs and complexity. The evolution of C++
has emphasized features that greatly reduce the need to use C-style idioms. The old C-programming facilities
are there when you need them, but with modern C++ code you should need them less and less. Modern C++
code is simpler, safer, more elegant, and still as fast as ever.
The following sections provide an overview of the main features of modern C++. Unless noted otherwise, the
features listed here are available in C++11 and later. In the Microsoft C++ compiler, you can set the /std
compiler option to specify which version of the standard to use for your project.
void functionUsingWidget() {
widget w(1000000); // lifetime automatically tied to enclosing scope
// constructs w, including the w.data gadget member
// ...
w.do_something();
// ...
} // automatic destruction and deallocation for w and w.data
Whenever possible, use a smart pointer when allocating heap memory. If you must use the new and delete
operators explicitly, follow the principle of RAII. For more information, see Object lifetime and resource
management (RAII).
vector<string> apples;
apples.push_back("Granny Smith");
Use map (not unordered_map ) as the default associative container. Use set , multimap , and multiset for
degenerate and multi cases.
int main()
{
std::vector<int> v {1,2,3};
// C-style
for(int i = 0; i < v.size(); ++i)
{
std::cout << v[i];
}
// Modern C++:
for(auto& num : v)
{
std::cout << num;
}
}
Uniform initialization
In modern C++, you can use brace initialization for any type. This form of initialization is especially convenient
when initializing arrays, vectors, or other containers. In the following example, v2 is initialized with three
instances of S . v3 is initialized with three instances of S that are themselves initialized using braces. The
compiler infers the type of each element based on the declared type of v3 .
#include <vector>
struct S
{
std::string name;
float num;
S(std::string s, float f) : name(s), num(f) {}
};
int main()
{
// C-style initialization
std::vector<S> v;
S s1("Norah", 2.7);
S s2("Frank", 3.5);
S s3("Jeri", 85.9);
v.push_back(s1);
v.push_back(s2);
v.push_back(s3);
// Modern C++:
std::vector<S> v2 {s1, s2, s3};
// or...
std::vector<S> v3{ {"Norah", 2.7}, {"Frank", 3.5}, {"Jeri", 85.9} };
Move semantics
Modern C++ provides move semantics, which make it possible to eliminate unnecessary memory copies. In
earlier versions of the language, copies were unavoidable in certain situations. A move operation transfers
ownership of a resource from one object to the next without making a copy. Some classes own resources such
as heap memory, file handles, and so on. When you implement a resource-owning class, you can define a move
constructor and move assignment operator for it. The compiler chooses these special members during overload
resolution in situations where a copy isn't needed. The Standard Library container types invoke the move
constructor on objects if one is defined. For more information, see Move Constructors and Move Assignment
Operators (C++).
Lambda expressions
In C-style programming, a function can be passed to another function by using a function pointer. Function
pointers are inconvenient to maintain and understand. The function they refer to may be defined elsewhere in
the source code, far away from the point at which it's invoked. Also, they're not type-safe. Modern C++ provides
function objects, classes that override the operator() operator, which enables them to be called like a function.
The most convenient way to create function objects is with inline lambda expressions. The following example
shows how to use a lambda expression to pass a function object, that the for_each function will invoke on each
element in the vector:
std::vector<int> v {1,2,3,4,5};
int x = 2;
int y = 4;
auto result = find_if(begin(v), end(v), [=](int i) { return i > x && i < y; });
The lambda expression [=](int i) { return i > x && i < y; } can be read as "function that takes a single
argument of type int and returns a boolean that indicates whether the argument is greater than x and less
than y ." Notice that the variables x and y from the surrounding context can be used in the lambda. The [=]
specifies that those variables are captured by value; in other words, the lambda expression has its own copies of
those values.
Exceptions
Modern C++ emphasizes exceptions rather than error codes as the best way to report and handle error
conditions. For more information, see Modern C++ best practices for exceptions and error handling.
std::atomic
Use the C++ Standard Library std::atomic struct and related types for inter-thread communication
mechanisms.
std::variant (C++17)
Unions are commonly used in C-style programming to conserve memory by enabling members of different
types to occupy the same memory location. However, unions aren't type-safe and are prone to programming
errors. C++17 introduces the std::variant class as a more robust and safe alternative to unions. The
std::visit function can be used to access the members of a variant type in a type-safe manner.
See also
C++ Language Reference
Lambda Expressions
C++ Standard Library
Microsoft C/C++ language conformance
Lexical conventions
3/24/2020 • 2 minutes to read • Edit Online
This section introduces the fundamental elements of a C++ program. You use these elements, called "lexical
elements" or "tokens" to construct statements, definitions, declarations, and so on, which are used to construct
complete programs. The following lexical elements are discussed in this section:
Tokens and character sets
Comments
Identifiers
Keywords
Punctuators
Numeric, boolean, and pointer literals
String and character literals
User-defined literals
For more information about how C++ source files are parsed, see Phases of translation.
See also
C++ Language Reference
Translation units and linkage
Tokens and character sets
3/6/2021 • 3 minutes to read • Edit Online
The text of a C++ program consists of tokens and white space. A token is the smallest element of a C++
program that is meaningful to the compiler. The C++ parser recognizes these kinds of tokens:
Keywords
Identifiers
Numeric, Boolean and Pointer Literals
String and Character Literals
User-Defined Literals
Operators
Punctuators
Tokens are usually separated by white space, which can be one or more:
Blanks
Horizontal or vertical tabs
New lines
Form feeds
Comments
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
Microsoft Specific
MSVC includes the $ character as a member of the basic source character set. MSVC also allows an additional
set of characters to be used in source files, based on the file encoding. By default, Visual Studio stores source
files by using the default codepage. When source files are saved by using a locale-specific codepage or a
Unicode codepage, MSVC allows you to use any of the characters of that code page in your source code, except
for the control codes not explicitly allowed in the basic source character set. For example, you can put Japanese
characters in comments, identifiers, or string literals if you save the file using a Japanese codepage. MSVC does
not allow character sequences that cannot be translated into valid multibyte characters or Unicode code points.
Depending on compiler options, not all allowed characters may appear in identifiers. For more information, see
Identifiers.
END Microsoft Specific
Universal character names
Because C++ programs can use many more characters than the ones specified in the basic source character set,
you can specify these characters in a portable way by using universal character names. A universal character
name consists of a sequence of characters that represent a Unicode code point. These take two forms. Use
\UNNNNNNNN to represent a Unicode code point of the form U+NNNNNNNN, where NNNNNNNN is the eight-
digit hexadecimal code point number. Use four-digit \uNNNN to represent a Unicode code point of the form
U+0000NNNN.
Universal character names can be used in identifiers and in string and character literals. A universal character
name cannot be used to represent a surrogate code point in the range 0xD800-0xDFFF. Instead, use the desired
code point; the compiler automatically generates any required surrogates. Additional restrictions apply to the
universal character names that can be used in identifiers. For more information, see Identifiers and String and
Character Literals.
Microsoft Specific
The Microsoft C++ compiler treats a character in universal character name form and literal form
interchangeably. For example, you can declare an identifier using universal character name form, and use it in
literal form:
The format of extended characters on the Windows clipboard is specific to application locale settings. Cutting
and pasting these characters into your code from another application may introduce unexpected character
encodings. This can result in parsing errors with no visible cause in your code. We recommend that you set your
source file encoding to a Unicode codepage before pasting extended characters. We also recommend that you
use an IME or the Character Map app to generate extended characters.
END Microsoft Specific
Execution character sets
The execution character sets represent the characters and strings that can appear in a compiled program. These
character sets consist of all the characters permitted in a source file, and also the control characters that
represent alert, backspace, carriage return, and the null character. The execution character set has a locale-
specific representation.
Comments (C++)
3/6/2021 • 2 minutes to read • Edit Online
A comment is text that the compiler ignores but that is useful for programmers. Comments are normally used to
annotate code for future reference. The compiler treats them as white space. You can use comments in testing to
make certain lines of code inactive; however, #if / #endif preprocessor directives work better for this because
you can surround code that contains comments but you cannot nest comments.
A C++ comment is written in one of the following ways:
The /* (slash, asterisk) characters, followed by any sequence of characters (including new lines),
followed by the */ characters. This syntax is the same as ANSI C.
The // (two slashes) characters, followed by any sequence of characters. A new line not immediately
preceded by a backslash terminates this form of comment. Therefore, it is commonly called a "single-line
comment."
The comment characters ( /* , */ , and // ) have no special meaning within a character constant, string literal,
or comment. Comments using the first syntax, therefore, cannot be nested.
See also
Lexical Conventions
Identifiers (C++)
3/6/2021 • 3 minutes to read • Edit Online
_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
Certain ranges of universal character names are also allowed in an identifier. A universal character name in an
identifier cannot designate a control character or a character in the basic source character set. For more
information, see Character Sets. These Unicode code point number ranges are allowed as universal character
names for any character in an identifier:
00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00B7-00BA, 00BC-00BE, 00C0-00D6, 00D8-00F6, 00F8-00FF, 0100-
02FF, 0370-167F, 1681-180D, 180F-1DBF, 1E00-1FFF, 200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F,
2070-20CF, 2100-218F, 2460-24FF, 2776-2793, 2C00-2DFF, 2E80-2FFF, 3004-3007, 3021-302F, 3031-303F,
3040-D7FF, F900-FD3D, FD40-FDCF, FDF0-FE1F, FE30-FE44, FE47-FFFD, 10000-1FFFD, 20000-2FFFD, 30000-
3FFFD, 40000-4FFFD, 50000-5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-
AFFFD, B0000-BFFFD, C0000-CFFFD, D0000-DFFFD, E0000-EFFFD
The following characters are allowed as any character in an identifier except the first:
0 1 2 3 4 5 6 7 8 9
These Unicode code point number ranges are also allowed as universal character names for any character in an
identifier except the first:
0300-036F, 1DC0-1DFF, 20D0-20FF, FE20-FE2F
Microsoft Specific
Only the first 2048 characters of Microsoft C++ identifiers are significant. Names for user-defined types are
"decorated" by the compiler to preserve type information. The resultant name, including the type information,
cannot be longer than 2048 characters. (See Decorated Names for more information.) Factors that can influence
the length of a decorated identifier are:
Whether the identifier denotes an object of user-defined type or a type derived from a user-defined type.
Whether the identifier denotes a function or a type derived from a function.
The number of arguments to a function.
The dollar sign $ is a valid identifier character in the Microsoft C++ compiler (MSVC). MSVC also allows you to
use the actual characters represented by the allowed ranges of universal character names in identifiers. To use
these characters, you must save the file by using a file encoding codepage that includes them. This example
shows how both extended characters and universal character names can be used interchangeably in your code.
// extended_identifier.cpp
// In Visual Studio, use File, Advanced Save Options to set
// the file encoding to Unicode codepage 1200
struct テスト // Japanese 'test'
{
void トスト() {} // Japanese 'toast'
};
int main() {
テスト \u30D1\u30F3; // Japanese パン 'bread' in UCN form
パン.トスト(); // compiler recognizes UCN or literal form
}
The range of characters allowed in an identifier is less restrictive when compiling C++/CLI code. Identifiers in
code compiled by using /clr should follow Standard ECMA-335: Common Language Infrastructure (CLI).
END Microsoft Specific
The first character of an identifier must be an alphabetic character, either uppercase or lowercase, or an
underscore ( _ ). Because C++ identifiers are case sensitive, fileName is different from FileName .
Identifiers cannot be exactly the same spelling and case as keywords. Identifiers that contain keywords are legal.
For example, Pint is a legal identifier, even though it contains int , which is a keyword.
Use of two sequential underscore characters ( __ ) in an identifier, or a single leading underscore followed by a
capital letter, is reserved for C++ implementations in all scopes. You should avoid using one leading underscore
followed by a lowercase letter for names with file scope because of possible conflicts with current or future
reserved identifiers.
See also
Lexical Conventions
Keywords (C++)
3/8/2021 • 3 minutes to read • Edit Online
Keywords are predefined reserved identifiers that have special meanings. They can't be used as identifiers in
your program. The following keywords are reserved for Microsoft C++. Names with leading underscores and
names specified for C++/CX and C++/CLI are Microsoft extensions.
constinit c
continue
co_await c
co_return c
co_yield c
decltype
default
delete
do
double
dynamic_cast
else
enum
explicit
c
export c
extern
false
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
noexcept
not b
not_eq b
nullptr
operator
or b
or_eq b
private
protected
public
register reinterpret_cast
requires c
return
short
signed
sizeof
static
static_assert
static_cast
struct
switch
template
this
thread_local
throw
true
try
typedef
typeid
typename
union
unsigned
using declaration
using directive
virtual
void
volatile
wchar_t
while
xor b
xor_eq b
a The Microsoft-specific __asm keyword replaces C++ asm syntax. asm is reserved for compatibility with other
C++ implementations, but not implemented. Use __asm for inline assembly on x86 targets. Microsoft C++
doesn't support Inline assembly for other targets.
b The extended operator synonyms are keywords when /permissive- or /Za (Disable language extensions) is
specified. They aren't keywords when Microsoft extensions are enabled.
c Supported when /std:c++latest is specified.
__hook d
__if_exists
__if_not_exists
__inline e
__int16 e
__int32 e
__int64 e
e
__int8 e
__interface
__leave e
__m128
__m128d
__m128i
__m64
__multiple_inheritance e
__ptr32 e
__ptr64 e
__raise
__restrict e
__single_inheritance e
__sptr e
__stdcall e
__super
__thiscall
__unaligned e
__unhook d
__uptr e
__uuidof e
__vectorcall e
__virtual_inheritance e
__w64 e
__wchar_t
e For
backward compatibility with previous versions, these keywords are available both with two leading
underscores and a single leading underscore when Microsoft extensions are enabled (the default).
dllexport
dllimport
jitintrinsic
naked
noalias
noinline
noreturn
no_sanitize_address
nothrow
novtable
process
property
restrict
safebuffers
selectany
spectre
thread
uuid
__try_cast f
__value f
abstract g
array g
as_friend
delegate g
enum class
enum struct
event g
finally
for each in
gcnew g
generic g
initonly
interface class g
interface struct g
interior_ptr g
literal g
new g
property g
ref class
ref struct
safecast
sealed g
typeid
g
value class g
value struct g
fApplicable to Managed Extensions for C++ only. This syntax is now deprecated. For more information, see
Component Extensions for Runtime Platforms.
g Applicable to C++/CLI.
See also
Lexical conventions
C++ built-in operators, precedence, and associativity
Punctuators (C++)
3/6/2021 • 2 minutes to read • Edit Online
Punctuators in C++ have syntactic and semantic meaning to the compiler but do not, of themselves, specify an
operation that yields a value. Some punctuators, either alone or in combination, can also be C++ operators or
be significant to the preprocessor.
Any of the following characters are considered punctuators:
! % ^ & * ( ) - + = { } | ~
[ ] \ ; ' : " < > ? , . / #
See also
Lexical Conventions
Numeric, boolean, and pointer literals
3/6/2021 • 5 minutes to read • Edit Online
A literal is a program element that directly represents a value. This article covers literals of type integer, floating-
point, boolean, and pointer. For information about string and character literals, see String and Character Literals
(C++). You can also define your own literals based on any of these categories. For more information, see User-
defined literals (C++).
You can use literals in many contexts, but most commonly to initialize named variables and to pass arguments
to functions:
Sometimes it's important to tell the compiler how to interpret a literal, or what specific type to give to it. It's
done by appending prefixes or suffixes to the literal. For example, the prefix 0x tells the compiler to interpret
the number that follows it as a hexadecimal value, for example 0x35 . The ULL suffix tells the compiler to treat
the value as an unsigned long long type, as in 5894345ULL . See the following sections for the complete list of
prefixes and suffixes for each literal type.
Integer literals
Integer literals begin with a digit and have no fractional parts or exponents. You can specify integer literals in
decimal, binary, octal, or hexadecimal form. You can optionally specify an integer literal as unsigned, and as a
long or long long type, by using a suffix.
When no prefix or suffix is present, the compiler will give an integral literal value type int (32 bits), if the value
will fit, otherwise it will give it type long long (64 bits).
To specify a decimal integral literal, begin the specification with a nonzero digit. For example:
To specify an octal integral literal, begin the specification with 0, followed by a sequence of digits in the range 0
through 7. The digits 8 and 9 are errors in specifying an octal literal. For example:
To specify a hexadecimal integral literal, begin the specification with 0x or 0X (the case of the "x" doesn't
matter), followed by a sequence of digits in the range 0 through 9 and a (or A ) through f (or F ).
Hexadecimal digits a (or A ) through f (or F ) represent values in the range 10 through 15. For example:
int i = 0x3fff; // Hexadecimal literal
int j = 0X3FFF; // Equal to i
To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix.
To specify a 64-bit integral type, use the LL, or ll suffix. The i64 suffix is still supported, but we don't recommend
it. It's specific to Microsoft and isn't portable. For example:
Digit separators : You can use the single-quote character (apostrophe) to separate place values in larger
numbers to make them easier for humans to read. Separators have no effect on compilation.
18.46
38.
The exponent, if present, specifies the magnitude of the number as a power of 10, as shown in the following
example:
18.46e0 // 18.46
18.46e1 // 184.6
The exponent may be specified using e or E , which have the same meaning, followed by an optional sign (+
or -) and a sequence of digits. If an exponent is present, the trailing decimal point is unnecessary in whole
numbers such as 18E0 .
Floating-point literals default to type double . By using the suffixes f or l or F or L (the suffix isn't case
sensitive), the literal can be specified as float or long double .
Although long double and double have the same representation, they're not the same type. For example, you
can have overloaded functions such as
and
void func( long double );
Boolean literals
The boolean literals are true and false .
In the previous example, a better practice is to use a named constant that conveys a clear meaning, for example
"MAXIMUM_ERROR_THRESHOLD". And if the return value "Success" is seen by end users, then it might be
better to use a named string constant. You can keep string constants in a single location in a file that can be
localized into other languages. Using named constants helps both yourself and others to understand the intent
of the code.
See also
Lexical conventions
C++ string literals
C++ user-defined literals
String and character literals (C++)
11/2/2020 • 17 minutes to read • Edit Online
C++ supports various string and character types, and provides ways to express literal values of each of these
types. In your source code, you express the content of your character and string literals using a character set.
Universal character names and escape characters allow you to express any string using only the basic source
character set. A raw string literal enables you to avoid using escape characters, and can be used to express all
types of string literals. You can also create std::string literals without having to perform extra construction or
conversion steps.
#include <string>
using namespace std::string_literals; // enables s-suffix for std::string literals
int main()
{
// Character literals
auto c0 = 'A'; // char
auto c1 = u8'A'; // char
auto c2 = L'A'; // wchar_t
auto c3 = u'A'; // char16_t
auto c4 = U'A'; // char32_t
// Multicharacter literals
auto m0 = 'abcd'; // int, value 0x61626364
// String literals
auto s0 = "hello"; // const char*
auto s1 = u8"hello"; // const char*, encoded as UTF-8
auto s2 = L"hello"; // const wchar_t*
auto s3 = u"hello"; // const char16_t*, encoded as UTF-16
auto s4 = U"hello"; // const char32_t*, encoded as UTF-32
String literals can have no prefix, or u8 , L , u , and U prefixes to denote narrow character (single-byte or
multi-byte), UTF-8, wide character (UCS-2 or UTF-16), UTF-16 and UTF-32 encodings, respectively. A raw string
literal can have R , u8R , LR , uR , and UR prefixes for the raw version equivalents of these encodings. To create
temporary or static std::string values, you can use string literals or raw string literals with an s suffix. For
more information, see the String literals section below. For more information on the basic source character set,
universal character names, and using characters from extended codepages in your source code, see Character
sets.
Character literals
A character literal is composed of a constant character. It's represented by the character surrounded by single
quotation marks. There are five kinds of character literals:
Ordinary character literals of type char , for example 'a'
UTF-8 character literals of type char ( char8_t in C++20), for example u8'a'
The character used for a character literal may be any character, except for the reserved characters backslash ( \ ),
single quotation mark ( ' ), or newline. Reserved characters can be specified by using an escape sequence.
Characters may be specified by using universal character names, as long as the type is large enough to hold the
character.
Encoding
Character literals are encoded differently based their prefix.
A character literal without a prefix is an ordinary character literal. The value of an ordinary character
literal containing a single character, escape sequence, or universal character name that can be
represented in the execution character set has a value equal to the numerical value of its encoding in the
execution character set. An ordinary character literal that contains more than one character, escape
sequence, or universal character name is a multicharacter literal. A multicharacter literal or an ordinary
character literal that can't be represented in the execution character set has type int , and its value is
implementation-defined. For MSVC, see the Microsoft-specific section below.
A character literal that begins with the L prefix is a wide-character literal. The value of a wide-character
literal containing a single character, escape sequence, or universal character name has a value equal to
the numerical value of its encoding in the execution wide-character set unless the character literal has no
representation in the execution wide-character set, in which case the value is implementation-defined.
The value of a wide-character literal containing multiple characters, escape sequences, or universal
character names is implementation-defined. For MSVC, see the Microsoft-specific section below.
A character literal that begins with the u8 prefix is a UTF-8 character literal. The value of a UTF-8
character literal containing a single character, escape sequence, or universal character name has a value
equal to its ISO 10646 code point value if it can be represented by a single UTF-8 code unit
(corresponding to the C0 Controls and Basic Latin Unicode block). If the value can't be represented by a
single UTF-8 code unit, the program is ill-formed. A UTF-8 character literal containing more than one
character, escape sequence, or universal character name is ill-formed.
A character literal that begins with the u prefix is a UTF-16 character literal. The value of a UTF-16
character literal containing a single character, escape sequence, or universal character name has a value
equal to its ISO 10646 code point value if it can be represented by a single UTF-16 code unit
(corresponding to the basic multi-lingual plane). If the value can't be represented by a single UTF-16 code
unit, the program is ill-formed. A UTF-16 character literal containing more than one character, escape
sequence, or universal character name is ill-formed.
A character literal that begins with the U prefix is a UTF-32 character literal. The value of a UTF-32
character literal containing a single character, escape sequence, or universal character name has a value
equal to its ISO 10646 code point value. A UTF-32 character literal containing more than one character,
escape sequence, or universal character name is ill-formed.
Escape sequences
There are three kinds of escape sequences: simple, octal, and hexadecimal. Escape sequences may be any of the
following values:
newline \n
backslash \\
horizontal tab \t
question mark ? or \?
vertical tab \v
backspace \b
carriage return \r
form feed \f
octal \ooo
alert (bell) \a
hexadecimal \xhhh
An octal escape sequence is a backslash followed by a sequence of one to three octal digits. An octal escape
sequence terminates at the first character that's not an octal digit, if encountered sooner than the third digit. The
highest possible octal value is \377 .
A hexadecimal escape sequence is a backslash followed by the character x , followed by a sequence of one or
more hexadecimal digits. Leading zeroes are ignored. In an ordinary or u8-prefixed character literal, the highest
hexadecimal value is 0xFF. In an L-prefixed or u-prefixed wide character literal, the highest hexadecimal value is
0xFFFF. In a U-prefixed wide character literal, the highest hexadecimal value is 0xFFFFFFFF.
This sample code shows some examples of escaped characters using ordinary character literals. The same
escape sequence syntax is valid for the other character literal types.
#include <iostream>
using namespace std;
int main() {
char newline = '\n';
char tab = '\t';
char backspace = '\b';
char backslash = '\\';
char nullChar = '\0';
cout << "Newline character: " << newline << "ending" << endl;
cout << "Tab character: " << tab << "ending" << endl;
cout << "Backspace character: " << backspace << "ending" << endl;
cout << "Backslash character: " << backslash << "ending" << endl;
cout << "Null character: " << nullChar << "ending" << endl;
}
/* Output:
Newline character:
ending
Tab character: ending
Backspace character:ending
Backslash character: \ending
Null character: ending
*/
The backslash character ( \ ) is a line-continuation character when it's placed at the end of a line. If you want a
backslash character to appear as a character literal, you must type two backslashes in a row ( \\ ). For more
information about the line continuation character, see Phases of Translation.
Microsoft-specific
To create a value from a narrow multicharacter literal, the compiler converts the character or character sequence
between single quotes into 8-bit values within a 32-bit integer. Multiple characters in the literal fill
corresponding bytes as needed from high-order to low-order. The compiler then converts the integer to the
destination type following the usual rules. For example, to create a char value, the compiler takes the low-order
byte. To create a wchar_t or char16_t value, the compiler takes the low-order word. The compiler warns that
the result is truncated if any bits are set above the assigned byte or word.
An octal escape sequence that appears to contain more than three digits is treated as a 3-digit octal sequence,
followed by the subsequent digits as characters in a multicharacter literal, which can give surprising results. For
example:
Escape sequences that appear to contain non-octal characters are evaluated as an octal sequence up to the last
octal character, followed by the remaining characters as the subsequent characters in a multicharacter literal.
Warning C4125 is generated if the first non-octal character is a decimal digit. For example:
An octal escape sequence that has a higher value than \377 causes error C2022: 'value-in-decimal': too big for
character.
An escape sequence that appears to have hexadecimal and non-hexadecimal characters is evaluated as a
multicharacter literal that contains a hexadecimal escape sequence up to the last hexadecimal character, followed
by the non-hexadecimal characters. A hexadecimal escape sequence that contains no hexadecimal digits causes
compiler error C2153: "hex literals must have at least one hex digit".
If a wide character literal prefixed with L contains a multicharacter sequence, the value is taken from the first
character, and the compiler raises warning C4066. Subsequent characters are ignored, unlike the behavior of the
equivalent ordinary multicharacter literal.
Surrogate Pairs
Universal character names can't encode values in the surrogate code point range D800-DFFF. For Unicode
surrogate pairs, specify the universal character name by using \UNNNNNNNN , where NNNNNNNN is the eight-
digit code point for the character. The compiler generates a surrogate pair if necessary.
In C++03, the language only allowed a subset of characters to be represented by their universal character
names, and allowed some universal character names that didn’t actually represent any valid Unicode characters.
This mistake was fixed in the C++11 standard. In C++11, both character and string literals and identifiers can
use universal character names. For more information on universal character names, see Character Sets. For
more information about Unicode, see Unicode. For more information about surrogate pairs, see Surrogate Pairs
and Supplementary Characters.
String literals
A string literal represents a sequence of characters that together form a null-terminated string. The characters
must be enclosed between double quotation marks. There are the following kinds of string literals:
Narrow string literals
A narrow string literal is a non-prefixed, double-quote delimited, null-terminated array of type const char[n] ,
where n is the length of the array in bytes. A narrow string literal may contain any graphic character except the
double quotation mark ( " ), backslash ( \ ), or newline character. A narrow string literal may also contain the
escape sequences listed above, and universal character names that fit in a byte.
You can construct a raw string literal that contains a newline (not the escaped character) in the source:
//#include <string>
//using namespace std::string_literals;
string str{ "hello"s };
string str2{ u8"Hello World" };
wstring str3{ L"hello"s };
u16string str4{ u"hello"s };
u32string str5{ U"hello"s };
std::string literals are defined in the namespace std::literals::string_literals in the <string> header file.
Because std::literals::string_literals , and std::literals are both declared as inline namespaces,
std::literals::string_literals is automatically treated as if it belonged directly in namespace std .
Notice that strlen() and wcslen() don't include the size of the terminating null character, whose size is equal
to the element size of the string type: one byte on a char* or char8_t* string, two bytes on wchar_t* or
char16_t* strings, and four bytes on char32_t* strings.
The maximum length of a string literal is 65,535 bytes. This limit applies to both narrow string literals and wide
string literals.
Modifying string literals
Because string literals (not including std::string literals) are constants, trying to modify them—for example,
str[2] = 'A' —causes a compiler error.
Microsoft-specific
In Microsoft C++, you can use a string literal to initialize a pointer to non-const char or wchar_t . This non-
const initialization is allowed in C99 code, but is deprecated in C++98 and removed in C++11. An attempt to
modify the string causes an access violation, as in this example:
You can cause the compiler to emit an error when a string literal is converted to a non-const character pointer
when you set the /Zc:strictStrings (Disable string literal type conversion) compiler option. We recommend it
for standards-compliant portable code. It's also a good practice to use the auto keyword to declare string
literal-initialized pointers, because it resolves to the correct (const) type. For example, this code example catches
an attempt to write to a string literal at compile time:
In some cases, identical string literals may be pooled to save space in the executable file. In string-literal pooling,
the compiler causes all references to a particular string literal to point to the same location in memory, instead
of having each reference point to a separate instance of the string literal. To enable string pooling, use the /GF
compiler option.
The Microsoft-specific section ends here.
Concatenating adjacent string literals
Adjacent wide or narrow string literals are concatenated. This declaration:
Using embedded hexadecimal escape codes to specify string literals can cause unexpected results. The following
example seeks to create a string literal that contains the ASCII 5 character, followed by the characters f, i, v, and e:
"\x05five"
The actual result is a hexadecimal 5F, which is the ASCII code for an underscore, followed by the characters i, v,
and e. To get the correct result, you can use one of these escape sequences:
"\005five" // Use octal literal.
"\x05" "five" // Use string splicing.
std::string literals, because they're std::string types, can be concatenated with the + operator that is
defined for basic_string types. They can also be concatenated in the same way as adjacent string literals. In
both cases, the string encoding and the suffix must match:
See also
Character sets
Numeric, Boolean, and pointer literals
User-Defined Literals
User-defined literals
11/2/2020 • 6 minutes to read • Edit Online
There are six major categories of literals in C++: integer, character, floating-point, string, boolean, and pointer.
Starting in C++ 11, you can define your own literals based on these categories, to provide syntactic shortcuts
for common idioms and increase type safety. For example, let's say you have a Distance class. You could define
a literal for kilometers and another one for miles, and encourage the user to be explicit about the units of
measure by writing: auto d = 42.0_km or auto d = 42.0_mi . There's no performance advantage or disadvantage
to user-defined literals; they're primarily for convenience or for compile-time type deduction. The Standard
Library has user-defined literals for std::string , for std::complex , and for units in time and duration
operations in the <chrono> header:
ReturnType operator "" _a(unsigned long long int); // Literal operator for user-defined INTEGRAL literal
ReturnType operator "" _b(long double); // Literal operator for user-defined FLOATING literal
ReturnType operator "" _c(char); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _d(wchar_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _e(char16_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _f(char32_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _g(const char*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _h(const wchar_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _i(const char16_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _g(const char32_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _r(const char*); // Raw literal operator
template<char...> ReturnType operator "" _t(); // Literal operator template
The operator names in the previous example are placeholders for whatever name you provide; however, the
leading underscore is required. (Only the Standard Library is allowed to define literals without the underscore.)
The return type is where you customize the conversion or other operations done by the literal. Also, any of these
operators can be defined as constexpr .
Cooked literals
In source code, any literal, whether user-defined or not, is essentially a sequence of alphanumeric characters,
such as 101 , or 54.7 , or "hello" or true . The compiler interprets the sequence as an integer, float, const
char* string, and so on. A user-defined literal that accepts as input whatever type the compiler assigned to the
literal value is informally known as a cooked literal. All the operators above except _r and _t are cooked
literals. For example, a literal 42.0_km would bind to an operator named _km that had a signature similar to _b
and the literal 42_km would bind to an operator with a signature similar to _a.
The following example shows how user-defined literals can encourage callers to be explicit about their input. To
construct a Distance , the user must explicitly specify kilometers or miles by using the appropriate user-defined
literal. You can achieve the same result in other ways, but user-defined literals are less verbose than the
alternatives.
// UDL_Distance.cpp
#include <iostream>
#include <string>
struct Distance
{
private:
explicit Distance(long double val) : kilometers(val)
{}
int main()
{
// Must have a decimal point to bind to the operator we defined!
Distance d{ 402.0_km }; // construct using kilometers
std::cout << "Kilometers in d: " << d.get_kilometers() << std::endl; // 402
std::string s;
std::getline(std::cin, s);
return 0;
}
The literal number must use a decimal. Otherwise, the number would be interpreted as an integer, and the type
wouldn't be compatible with the operator. For floating point input, the type must be long double , and for
integral types it must be long long .
Raw literals
In a raw user-defined literal, the operator that you define accepts the literal as a sequence of char values. It's up
to you to interpret that sequence as a number or string or other type. In the list of operators shown earlier in
this page, _r and _t can be used to define raw literals:
You can use raw literals to provide a custom interpretation of an input sequence that's different than the
compiler's normal behavior. For example, you could define a literal that converts the sequence 4.75987 into a
custom Decimal type instead of an IEEE 754 floating point type. Raw literals, like cooked literals, can also be used
for compile-time validation of input sequences.
Example: Limitations of raw literals
The raw literal operator and literal operator template only work for integral and floating-point user-defined
literals, as shown by the following example:
#include <cstddef>
#include <cstdio>
// There is no raw literal operator or literal operator template support on these types:
// 'A'_dump_raw;
// L'B'_dump_raw;
// u'C'_dump_raw;
// U'D'_dump_raw;
// "Hello World"_dump_raw;
// L"Wide String"_dump_raw;
// u8"UTF-8 String"_dump_raw;
// u"UTF-16 String"_dump_raw;
// U"UTF-32 String"_dump_raw;
}
This section explains concepts that are critical to understanding C++. C programmers will be familiar with many
of these concepts, but there are some subtle differences that can cause unexpected program results. The
following topics are included:
C++ type system
Scope
Translation units and linkage
main function and command-line arguments
Program termination
Lvalues and rvalues
Temporary objects
Alignment
Trivial, standard-layout and POD types
See also
C++ Language Reference
C++ type system
6/30/2021 • 13 minutes to read • Edit Online
The concept of type is very important in C++. Every variable, function argument, and function return value must
have a type in order to be compiled. Also, every expression (including literal values) is implicitly given a type by
the compiler before it is evaluated. Some examples of types include int to store integer values, double to
store floating-point values (also known as scalar data types), or the Standard Library class std::basic_string to
store text. You can create your own type by defining a class or struct . The type specifies the amount of
memory that will be allocated for the variable (or expression result), the kinds of values that may be stored in
that variable, how those values (as bit patterns) are interpreted, and the operations that can be performed on it.
This article contains an informal overview of the major features of the C++ type system.
Terminology
Variable : The symbolic name of a quantity of data so that the name can be used to access the data it refers to
throughout the scope of the code where it is defined. In C++, variable is generally used to refer to instances of
scalar data types, whereas instances of other types are usually called objects.
Object : For simplicity and consistency, this article uses the term object to refer to any instance of a class or
structure, and when it is used in the general sense includes all types, even scalar variables.
POD type (plain old data): This informal category of data types in C++ refers to types that are scalar (see the
Fundamental types section) or are POD classes. A POD class has no static data members that aren’t also PODs,
and has no user-defined constructors, user-defined destructors, or user-defined assignment operators. Also, a
POD class has no virtual functions, no base class, and no private or protected non-static data members. POD
types are often used for external data interchange, for example with a module written in the C language (which
has POD types only).
The following table lists the most frequently used fundamental types, and their sizes in the Microsoft C++
implementation:
TYPE SIZ E C O M M EN T
Other C++ implementations may use different sizes for certain numeric types. For more information on the
sizes and size relationships that the C++ standard requires, see Built-in types.
The const qualifier is used extensively in function and variable declarations and "const correctness" is an
important concept in C++; essentially it means to use const to guarantee, at compile time, that values are not
modified unintentionally. For more information, see const .
A const type is distinct from its non-const version; for example, const int is a distinct type from int . You can
use the C++ const_cast operator on those rare occasions when you must remove const-ness from a variable.
For more information, see Type Conversions and Type Safety.
String types
Strictly speaking, the C++ language has no built-in string type; char and wchar_t store single characters - you
must declare an array of these types to approximate a string, adding a terminating null value (for example, ASCII
'\0' ) to the array element one past the last valid character (also called a C-style string). C-style strings required
much more code to be written or the use of external string utility library functions. But in modern C++, we have
the Standard Library types std::string (for 8-bit char -type character strings) or std::wstring (for 16-bit
wchar_t -type character strings). These C++ Standard Library containers can be thought of as native string
types because they are part of the standard libraries that are included in any compliant C++ build environment.
Simply use the #include <string> directive to make these types available in your program. (If you are using
MFC or ATL, the CString class is also available, but is not part of the C++ standard.) The use of null-terminated
character arrays (the C-style strings previously mentioned) is strongly discouraged in modern C++.
User-defined types
When you define a class , struct , union , or enum , that construct is used in the rest of your code as if it were a
fundamental type. It has a known size in memory, and certain rules about how it can be used apply to it for
compile-time checking and, at runtime, for the life of your program. The primary differences between the
fundamental built-in types and user-defined types are as follows:
The compiler has no built-in knowledge of a user-defined type. It learns of the type when it first
encounters the definition during the compilation process.
You specify what operations can be performed on your type, and how it can be converted to other types,
by defining (through overloading) the appropriate operators, either as class members or non-member
functions. For more information, see Function Overloading
Pointer types
Dating back to the earliest versions of the C language, C++ continues to let you declare a variable of a pointer
type by using the special declarator * (asterisk). A pointer type stores the address of the location in memory
where the actual data value is stored. In modern C++, these are referred to as raw pointers, and are accessed in
your code through special operators * (asterisk) or -> (dash with greater-than). This is called dereferencing,
and which one that you use depends on whether you are dereferencing a pointer to a scalar or a pointer to a
member in an object. Working with pointer types has long been one of the most challenging and confusing
aspects of C and C++ program development. This section outlines some facts and practices to help use raw
pointers if you want to, but in modern C++ it’s no longer required (or recommended) to use raw pointers for
object ownership at all, due to the evolution of the smart pointer (discussed more at the end of this section). It is
still useful and safe to use raw pointers for observing objects, but if you must use them for object ownership,
you should do so with caution and very careful consideration of how the objects owned by them are created
and destroyed.
The first thing that you should know is declaring a raw pointer variable will allocate only the memory that is
required to store an address of the memory location that the pointer will be referring to when it is dereferenced.
Allocation of the memory for the data value itself (also called backing store) is not yet allocated. In other words,
by declaring a raw pointer variable, you are creating a memory address variable, not an actual data variable.
Dereferencing a pointer variable before making sure that it contains a valid address to a backing store will cause
undefined behavior (usually a fatal error) in your program. The following example demonstrates this kind of
error:
int* pNumber; // Declare a pointer-to-int variable.
*pNumber = 10; // error. Although this may compile, it is
// a serious error. We are dereferencing an
// uninitialized pointer variable with no
// allocated memory to point to.
The example dereferences a pointer type without having any memory allocated to store the actual integer data
or a valid memory address assigned to it. The following code corrects these errors:
The corrected code example uses local stack memory to create the backing store that pNumber points to. We use
a fundamental type for simplicity. In practice, the backing store for pointers are most often user-defined types
that are dynamically-allocated in an area of memory called the heap (or free store) by using a new keyword
expression (in C-style programming, the older malloc() C runtime library function was used). Once allocated,
these variables are usually referred to as objects, especially if they are based on a class definition. Memory that
is allocated with new must be deleted by a corresponding delete statement (or, if you used the malloc()
function to allocate it, the C runtime function free() ).
However, it is easy to forget to delete a dynamically-allocated object- especially in complex code, which causes a
resource bug called a memory leak. For this reason, the use of raw pointers is strongly discouraged in modern
C++. It is almost always better to wrap a raw pointer in a smart pointer, which will automatically release the
memory when its destructor is invoked (when the code goes out of scope for the smart pointer); by using smart
pointers you virtually eliminate a whole class of bugs in your C++ programs. In the following example, assume
MyClass is a user-defined type that has a public method DoSomeWork();
void someFunction() {
unique_ptr<MyClass> pMc(new MyClass);
pMc->DoSomeWork();
}
// No memory leak. Out-of-scope automatically calls the destructor
// for the unique_ptr, freeing the resource.
More information
For more information about the C++ type system, see the following topics.
Value Types
Describes value types along with issues relating to their use.
Type Conversions and Type Safety
Describes common type conversion issues and shows how to avoid them.
See also
Welcome back to C++
C++ Language Reference
C++ Standard Library
Scope (C++)
3/6/2021 • 4 minutes to read • Edit Online
When you declare a program element such as a class, function, or variable, its name can only be "seen" and used
in certain parts of your program. The context in which a name is visible is called its scope. For example, if you
declare a variable x within a function, x is only visible within that function body. It has local scope. You may
have other variables by the same name in your program; as long as they are in different scopes, they do not
violate the One Definition Rule and no error is raised.
For automatic non-static variables, scope also determines when they are created and destroyed in program
memory.
There are six kinds of scope:
Global scope A global name is one that is declared outside of any class, function, or namespace.
However, in C++ even these names exist with an implicit global namespace. The scope of global names
extends from the point of declaration to the end of the file in which they are declared. For global names,
visibility is also governed by the rules of linkage which determine whether the name is visible in other
files in the program.
Namespace scope A name that is declared within a namespace, outside of any class or enum definition
or function block, is visible from its point of declaration to the end of the namespace. A namespace may
be defined in multiple blocks across different files.
Local scope A name declared within a function or lambda, including the parameter names, have local
scope. They are often referred to as "locals". They are only visible from their point of declaration to the
end of the function or lambda body. Local scope is a kind of block scope, which is discussed later in this
article.
Class scope Names of class members have class scope, which extends throughout the class definition
regardless of the point of declaration. Class member accessibility is further controlled by the public ,
private , and protected keywords. Public or protected members can be accessed only by using the
member-selection operators (. or -> ) or pointer-to-member operators (.* or -> * ).
Statement scope Names declared in a for , if , while , or switch statement are visible until the end
of the statement block.
Function scope A label has function scope, which means it is visible throughout a function body even
before its point of declaration. Function scope makes it possible to write statements like goto cleanup
before the cleanup label is declared.
Hiding Names
You can hide a name by declaring it in an enclosed block. In the following figure, i is redeclared within the
inner block, thereby hiding the variable associated with i in the outer block scope.
Block scope and name hiding
The output from the program shown in the figure is:
i = 0
i = 7
j = 9
i = 0
NOTE
The argument szWhat is considered to be in the scope of the function. Therefore, it is treated as if it had been declared
in the outermost block of the function.
// hiding_class_names.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
class Account Checking( Account ); // Qualifies Account as
// class name
The following example demonstrates how to declare a pointer to an object of type Account using the class
keyword:
The Account in the initializer (in parentheses) in the preceding statement has global scope; it is of type double .
NOTE
The reuse of identifier names as shown in this example is considered poor programming style.
For information about declaration and initialization of class objects, see Classes, Structures, and Unions. For
information about using the new and delete free-store operators, see new and delete operators.
#include <iostream>
See also
Basic Concepts
Header files (C++)
3/6/2021 • 4 minutes to read • Edit Online
The names of program elements such as variables, functions, classes, and so on must be declared before they
can be used. For example, you can't just write x = 42 without first declaring 'x'.
int x; // declaration
x = 42; // use x
The declaration tells the compiler whether the element is an int , a double , a function , a class or some other
thing. Furthermore, each name must be declared (directly or indirectly) in every .cpp file in which it is used.
When you compile a program, each .cpp file is compiled independently into a compilation unit. The compiler has
no knowledge of what names are declared in other compilation units. That means that if you define a class or
function or global variable, you must provide a declaration of that thing in each additional .cpp file that uses it.
Each declaration of that thing must be exactly identical in all files. A slight inconsistency will cause errors, or
unintended behavior, when the linker attempts to merge all the compilation units into a single program.
To minimize the potential for errors, C++ has adopted the convention of using header files to contain
declarations. You make the declarations in a header file, then use the #include directive in every .cpp file or other
header file that requires that declaration. The #include directive inserts a copy of the header file directly into the
.cpp file prior to compilation.
NOTE
In Visual Studio 2019, the C++20 modules feature is introduced as an improvement and eventual replacement for header
files. For more information, see Overview of modules in C++.
Example
The following example shows a common way to declare a class and then use it in a different source file. We'll
start with the header file, my_class.h . It contains a class definition, but note that the definition is incomplete; the
member function do_something is not defined:
// my_class.h
namespace N
{
class my_class
{
public:
void do_something();
};
Next, create an implementation file (typically with a .cpp or similar extension). We'll call the file my_class.cpp and
provide a definition for the member declaration. We add an #include directive for "my_class.h" file in order to
have the my_class declaration inserted at this point in the .cpp file, and we include <iostream> to pull in the
declaration for std::cout . Note that quotes are used for header files in the same directory as the source file,
and angle brackets are used for standard library headers. Also, many standard library headers do not have .h or
any other file extension.
In the implementation file, we can optionally use a using statement to avoid having to qualify every mention of
"my_class" or "cout" with "N::" or "std::". Don't put using statements in your header files!
// my_class.cpp
#include "my_class.h" // header in local directory
#include <iostream> // header in standard library
using namespace N;
using namespace std;
void my_class::do_something()
{
cout << "Doing something!" << endl;
}
Now we can use my_class in another .cpp file. We #include the header file so that the compiler pulls in the
declaration. All the compiler needs to know is that my_class is a class that has a public member function called
do_something() .
// my_program.cpp
#include "my_class.h"
using namespace N;
int main()
{
my_class mc;
mc.do_something();
return 0;
}
After the compiler finishes compiling each .cpp file into .obj files, it passes the .obj files to the linker. When the
linker merges the object files it finds exactly one definition for my_class; it is in the .obj file produced for
my_class.cpp, and the build succeeds.
Include guards
Typically, header files have an include guard or a #pragma once directive to ensure that they are not inserted
multiple times into a single .cpp file.
// my_class.h
#ifndef MY_CLASS_H // include guard
#define MY_CLASS_H
namespace N
{
class my_class
{
public:
void do_something();
};
}
#endif /* MY_CLASS_H */
private:
vstr vals;
int i;
};
struct RGB
{
short r{ 0 }; // member initialization
short g{ 0 };
short b{ 0 };
};
In a C++ program, a symbol, for example a variable or function name, can be declared any number of times
within its scope, but it can only be defined once. This rule is the "One Definition Rule" (ODR). A declaration
introduces (or re-introduces) a name into the program. A definition introduces a name. If the name represents a
variable, a definition explicitly initializes it. A function definition consists of the signature plus the function body.
A class definition consists of the class name followed by a block that lists all the class members. (The bodies of
member functions may optionally be defined separately in another file.)
The following example shows some declarations:
int i;
int f(int x);
class C;
int i{42};
int f(int x){ return x * i; }
class C {
public:
void DoSomething();
};
A program consists of one or more translation units. A translation unit consists of an implementation file and all
the headers that it includes directly or indirectly. Implementation files typically have a file extension of cpp or cxx.
Header files typically have an extension of h or hpp. Each translation unit is compiled independently by the
compiler. After the compilation is complete, the linker merges the compiled translation units into a single
program. Violations of the ODR rule typically show up as linker errors. Linker errors occur when the same name
has two different definitions in different translation units.
In general, the best way to make a variable visible across multiple files is to put it in a header file. Then add an
#include directive in every cpp file that requires the declaration. By adding include guards around the header
contents, you ensure that the names it declares are only defined once.
In C++20, modules are introduced as an improved alternative to header files.
In some cases it may be necessary to declare a global variable or class in a cpp file. In those cases, you need a
way to tell the compiler and linker what kind of linkage the name has. The type of linkage specifies whether the
name of the object applies just to the one file, or to all files. The concept of linkage applies only to global names.
The concept of linkage does not apply to names that are declared within a scope. A scope is specified by a set of
enclosing braces such as in function or class definitions.
See also
Basic Concepts
main function and command-line arguments
3/6/2021 • 8 minutes to read • Edit Online
All C++ programs must have a main function. If you try to compile a C++ program without a main function,
the compiler raises an error. (Dynamic-link libraries and static libraries don't have a main function.) The main
function is where your source code begins execution, but before a program enters the main function, all static
class members without explicit initializers are set to zero. In Microsoft C++, global static objects are also
initialized before entry to main . Several restrictions apply to the main function that don't apply to any other
C++ functions. The main function:
Can't be overloaded (see Function overloading).
Can't be declared as inline .
Can't be declared as static .
Can't have its address taken.
Can't be called from your program.
int main();
int main(int argc, char *argv[]);
If no return value is specified in main , the compiler supplies a return value of zero.
Microsoft-specific extensions
The following sections describe Microsoft-specific behavior.
int wmain();
int wmain(int argc, wchar_t *argv[]);
You can also use the Microsoft-specific _tmain , which is a preprocessor macro defined in tchar.h . _tmain
resolves to main unless _UNICODE is defined. In that case, _tmain resolves to wmain . The _tmain macro and
other macros that begin with _t are useful for code that must build separate versions for both narrow and
wide character sets. For more information, see Using generic-text mappings.
envp
The optional envp parameter is an array of strings representing the variables set in the user's environment. This
array is terminated by a NULL entry. It can be declared as an array of pointers to char ( char *envp[] ) or as a
pointer to pointers to char ( char **envp ). If your program uses wmain instead of main , use the wchar_t data
type instead of char .
The environment block passed to main and wmain is a "frozen" copy of the current environment. If you later
change the environment by making a call to putenv or _wputenv , the current environment (as returned by
getenv or _wgetenv and the _environ or _wenviron variable) will change, but the block pointed to by envp
won't change. For more information on how to suppress environment processing, see Customize C++
command-line processing. The envp argument is compatible with the C89 standard, but not with C++
standards.
Example arguments to main
The following example shows how to use the argc , argv , and envp arguments to main :
// argument_definitions.cpp
// compile with: /EHsc
#include <iostream>
#include <string.h>
// command_line_arguments.cpp
// compile with: /EHsc
#include <iostream>
"abc" d e abc d e
a\\\"b c d a\"b c d
a"b"" c d ab" c d
Wildcard expansion
The Microsoft compiler optionally allows you to use wildcard characters, the question mark ( ? ) and asterisk (
* ), to specify filename and path arguments on the command line.
Command-line arguments are handled by an internal routine in the runtime startup code, which by default
doesn't expand wildcards into separate strings in the argv string array. You can enable wildcard expansion by
including the setargv.obj file ( wsetargv.obj file for wmain ) in your /link compiler options or your LINK
command line.
For more information on runtime startup linker options, see Link options.
See also
Basic concepts
C++ program termination
3/6/2021 • 2 minutes to read • Edit Online
exit function
The exit function, declared in <stdlib.h>, terminates a C++ program. The value supplied as an argument to
exit is returned to the operating system as the program's return code or exit code. By convention, a return
code of zero means that the program completed successfully. You can use the constants EXIT_FAILURE and
EXIT_SUCCESS , also defined in <stdlib.h>, to indicate success or failure of your program.
Issuing a return statement from the main function is equivalent to calling the exit function with the return
value as its argument.
abort function
The abort function, also declared in the standard include file <stdlib.h>, terminates a C++ program. The
difference between exit and abort is that exit allows the C++ run-time termination processing to take
place (global object destructors get called), but abort terminates the program immediately. The abort function
bypasses the normal destruction process for initialized global static objects. It also bypasses any special
processing that was specified using the atexit function.
atexit function
Use the atexit function to specify actions that execute before the program terminates. No global static objects
initialized before the call to atexit are destroyed before execution of the exit-processing function.
// return_statement.cpp
#include <stdlib.h>
int main()
{
exit( 3 );
return 3;
}
The exit and return statements in the preceding example are functionally identical. Normally, C++ requires
that functions that have return types other than void return a value. The main function is an exception; it can
end without a return statement. In that case, it returns an implementation-specific value to the invoking
process. The return statement allows you to specify a return value from main .
Destruction of static objects
When you call exit or execute a return statement from main , static objects are destroyed in the reverse
order of their initialization (after the call to atexit if one exists). The following example shows how such
initialization and cleanup works.
Example
In the following example, the static objects sd1 and sd2 are created and initialized before entry to main . After
this program terminates using the return statement, first sd2 is destroyed and then sd1 . The destructor for
the ShowData class closes the files associated with these static objects.
// using_exit_or_return1.cpp
#include <stdio.h>
class ShowData {
public:
// Constructor opens a file.
ShowData( const char *szDev ) {
errno_t err;
err = fopen_s(&OutputDev, szDev, "w" );
}
int main() {
sd1.Disp( "hello to default device\n" );
sd2.Disp( "hello to file hello.dat\n" );
}
Another way to write this code is to declare the ShowData objects with block scope, allowing them to be
destroyed when they go out of scope:
int main() {
ShowData sd1( "CON" ), sd2( "hello.dat" );
See also
main function and command-line arguments
Lvalues and Rvalues (C++)
3/6/2021 • 2 minutes to read • Edit Online
Every C++ expression has a type, and belongs to a value category. The value categories are the basis for rules
that compilers must follow when creating, copying, and moving temporary objects during expression
evaluation.
The C++17 standard defines expression value categories as follows:
A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.
A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the
operand of an operator, as specified by the context in which it appears.
An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is
near the end of its lifetime). Example: Certain kinds of expressions involving rvalue references (8.3.2) yield
xvalues, such as a call to a function whose return type is an rvalue reference or a cast to an rvalue reference
type.
An lvalue is a glvalue that is not an xvalue.
An rvalue is a prvalue or an xvalue.
The following diagram illustrates the relationships between the categories:
An lvalue has an address that your program can access. Examples of lvalue expressions include variable names,
including const variables, array elements, function calls that return an lvalue reference, bit-fields, unions, and
class members.
A prvalue expression has no address that is accessible by your program. Examples of prvalue expressions
include literals, function calls that return a non-reference type, and temporary objects that are created during
expression evalution but accessible only by the compiler.
An xvalue expression has an address that no longer accessible by your program but can be used to initialize an
rvalue reference, which provides access to the expression. Examples include function calls that return an rvalue
reference, and the array subscript, member and pointer to member expressions where the array or object is an
rvalue reference.
Example
The following example demonstrates several correct and incorrect usages of lvalues and rvalues:
// lvalues_and_rvalues2.cpp
int main()
{
int i, j, *p;
NOTE
The examples in this topic illustrate correct and incorrect usage when operators are not overloaded. By overloading
operators, you can make an expression such as j * 4 an lvalue.
The terms lvalue and rvalue are often used when you refer to object references. For more information about
references, see Lvalue Reference Declarator: & and Rvalue Reference Declarator: &&.
See also
Basic Concepts
Lvalue Reference Declarator: &
Rvalue Reference Declarator: &&
Temporary Objects
3/6/2021 • 2 minutes to read • Edit Online
In some cases, it is necessary for the compiler to create temporary objects. These temporary objects can be
created for the following reasons:
To initialize a const reference with an initializer of a type different from that of the underlying type of the
reference being initialized.
To store the return value of a function that returns a user-defined type. These temporaries are created
only if your program does not copy the return value to an object. For example:
...
Because the return value is not copied to another object, a temporary object is created. A more common
case where temporaries are created is during the evaluation of an expression where overloaded operator
functions must be called. These overloaded operator functions return a user-defined type that often is not
copied to another object.
Consider the expression ComplexResult = Complex1 + Complex2 + Complex3 . The expression
Complex1 + Complex2 is evaluated, and the result is stored in a temporary object. Next, the expression
temporary + Complex3 is evaluated, and the result is copied to ComplexResult (assuming the assignment
operator is not overloaded).
To store the result of a cast to a user-defined type. When an object of a given type is explicitly converted
to a user-defined type, that new object is constructed as a temporary object.
Temporary objects have a lifetime that is defined by their point of creation and the point at which they are
destroyed. Any expression that creates more than one temporary object eventually destroys them in the reverse
order in which they were created. The points at which destruction occurs are shown in the following table.
Destruction Points for Temporary Objects
REA SO N T EM P O RA RY C REAT ED DEST RUC T IO N P O IN T
Initializing const references If an initializer is not an l-value of the same type as the
reference being initialized, a temporary of the underlying
object type is created and initialized with the initialization
expression. This temporary object is destroyed immediately
after the reference object to which it is bound is destroyed.
Alignment
11/2/2020 • 4 minutes to read • Edit Online
One of the low-level features of C++ is the ability to specify the precise alignment of objects in memory to take
maximum advantage of a specific hardware architecture. By default, the compiler aligns class and struct
members on their size value: bool and char on 1-byte boundaries, short on 2-byte boundaries, int , long ,
and float on 4-byte boundaries, and long long , double , and long double on 8-byte boundaries.
In most scenarios, you never have to be concerned with alignment because the default alignment is already
optimal. In some cases, however, you can achieve significant performance improvements, or memory savings,
by specifying a custom alignment for your data structures. Before Visual Studio 2015 you could use the
Microsoft-specific keywords __alignof and __declspec(align) to specify an alignment greater than the default.
Starting in Visual Studio 2015 you should use the C++11 standard keywords alignof and alignas for
maximum code portability. The new keywords behave in the same way under the hood as the Microsoft-specific
extensions. The documentation for those extensions also applies to the new keywords. For more information,
see alignof Operator and align. The C++ standard doesn't specify packing behavior for alignment on
boundaries smaller than the compiler default for the target platform, so you still need to use the Microsoft
#pragma pack in that case.
Use the aligned_storage class for memory allocation of data structures with custom alignments. The
aligned_union class is for specifying alignment for unions with non-trivial constructors or destructors.
Example
You can use alignas on a class, struct or union, or on individual members. When multiple alignas specifiers
are encountered, the compiler will choose the strictest one, (the one with the largest value).
// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
See also
Data structure alignment
Trivial, standard-layout, POD, and literal types
3/6/2021 • 5 minutes to read • Edit Online
The term layout refers to how the members of an object of class, struct or union type are arranged in memory.
In some cases, the layout is well-defined by the language specification. But when a class or struct contains
certain C++ language features such as virtual base classes, virtual functions, members with different access
control, then the compiler is free to choose a layout. That layout may vary depending on what optimizations are
being performed and in many cases the object might not even occupy a contiguous area of memory. For
example, if a class has virtual functions, all the instances of that class might share a single virtual function table.
Such types are very useful, but they also have limitations. Because the layout is undefined they cannot be passed
to programs written in other languages, such as C, and because they might be non-contiguous they cannot be
reliably copied with fast low-level functions such as memcopy , or serialized over a network.
To enable compilers as well as C++ programs and metaprograms to reason about the suitability of any given
type for operations that depend on a particular memory layout, C++14 introduced three categories of simple
classes and structs: trivial, standard-layout, and POD or Plain Old Data. The Standard Library has the function
templates is_trivial<T> , is_standard_layout<T> and is_pod<T> that determine whether a given type belongs
to a given category.
Trivial types
When a class or struct in C++ has compiler-provided or explicitly defaulted special member functions, then it is
a trivial type. It occupies a contiguous memory area. It can have members with different access specifiers. In
C++, the compiler is free to choose how to order members in this situation. Therefore, you can memcopy such
objects but you cannot reliably consume them from a C program. A trivial type T can be copied into an array of
char or unsigned char, and safely copied back into a T variable. Note that because of alignment requirements,
there might be padding bytes between type members.
Trivial types have a trivial default constructor, trivial copy constructor, trivial copy assignment operator and trivial
destructor. In each case, trivial means the constructor/operator/destructor is not user-provided and belongs to a
class that has
no virtual functions or virtual base classes,
no base classes with a corresponding non-trivial constructor/operator/destructor
no data members of class type with a corresponding non-trivial constructor/operator/destructor
The following examples show trivial types. In Trivial2, the presence of the Trivial2(int a, int b) constructor
requires that you provide a default constructor. For the type to qualify as trivial, you must explicitly default that
constructor.
struct Trivial
{
int i;
private:
int j;
};
struct Trivial2
{
int i;
Trivial2(int a, int b) : i(a), j(b) {}
Trivial2() = default;
private:
int j; // Different access control
};
struct SL
{
// All members have same access:
int i;
int j;
SL(int a, int b) : i(a), j(b) {} // User-defined constructor OK
};
The last two requirements can perhaps be better illustrated with code. In the next example, even though Base is
standard-layout, Derived is not standard layout because both it (the most derived class) and Base have non-
static data members:
struct Base
{
int i;
int j;
};
// std::is_standard_layout<<Derived> == false!
struct Derived : public Base
{
int x;
int y;
};
In this example Derived is standard-layout because Base has no non-static data members:
struct Base
{
void Foo() {}
};
// std::is_standard_layout<<Derived> == true
struct Derived : public Base
{
int x;
int y;
};
Derived would also be standard-layout if Base had the data members and Derived had only member
functions.
POD types
When a class or struct is both trivial and standard-layout, it is a POD (Plain Old Data) type. The memory layout
of POD types is therefore contiguous and each member has a higher address than the member that was
declared before it, so that byte for byte copies and binary I/O can be performed on these types. Scalar types
such as int are also POD types. POD types that are classes can have only POD types as non-static data members.
Example
The following example shows the distinctions between trivial, standard-layout, and POD types:
#include <type_traits>
#include <iostream>
struct B
{
protected:
virtual void Foo() {}
};
struct POD
{
int a;
int b;
};
int main()
{
cout << boolalpha;
cout << "A is trivial is " << is_trivial<A>() << endl; // false
cout << "A is standard-layout is " << is_standard_layout<A>() << endl; // false
cout << "C is trivial is " << is_trivial<C>() << endl; // true
cout << "C is standard-layout is " << is_standard_layout<C>() << endl; // false
cout << "D is trivial is " << is_trivial<D>() << endl; // false
cout << "D is standard-layout is " << is_standard_layout<D>() << endl; // true
cout << "POD is trivial is " << is_trivial<POD>() << endl; // true
cout << "POD is standard-layout is " << is_standard_layout<POD>() << endl; // true
return 0;
}
Literal types
A literal type is one whose layout can be determined at compile time. The following are the literal types:
void
scalar types
references
Arrays of void, scalar types or references
A class that has a trivial destructor, and one or more constexpr constructors that are not move or copy
constructors. Additionally, all its non-static data members and base classes must be literal types and not
volatile.
See also
Basic Concepts
C++ classes as value types
3/6/2021 • 3 minutes to read • Edit Online
C++ classes are by default value types. They can be specified as reference types, which enable polymorphic
behavior to support object-oriented programming. Value types are sometimes viewed from the perspective of
memory and layout control, whereas reference types are about base classes and virtual functions for
polymorphic purposes. By default, value types are copyable, which means there is always a copy constructor and
a copy assignment operator. For reference types, you make the class non-copyable (disable the copy constructor
and copy assignment operator) and use a virtual destructor, which supports their intended polymorphism. Value
types are also about the contents, which, when they are copied, always give you two independent values that
can be modified separately. Reference types are about identity - what kind of object is it? For this reason,
"reference types" are also referred to as "polymorphic types".
If you really want a reference-like type (base class, virtual functions), you need to explicitly disable copying, as
shown in the MyRefType class in the following code.
class MyRefType {
private:
MyRefType & operator=(const MyRefType &);
MyRefType(const MyRefType &);
public:
MyRefType () {}
};
int main()
{
MyRefType Data1, Data2;
// ...
Data1 = Data2;
}
test.cpp(15) : error C2248: 'MyRefType::operator =' : cannot access private member declared in class
'MyRefType'
meow.cpp(5) : see declaration of 'MyRefType::operator ='
meow.cpp(3) : see declaration of 'MyRefType'
#include <set>
#include <vector>
#include <string>
using namespace std;
//...
set<widget> LoadHugeData() {
set<widget> ret;
// ... load data from disk and populate ret
return ret;
}
//...
widgets = LoadHugeData(); // efficient, no deep copy
vector<string> v = IfIHadAMillionStrings();
v.insert( begin(v)+v.size()/2, "scott" ); // efficient, no deep copy-shuffle
v.insert( begin(v)+v.size()/2, "Andrei" ); // (just 1M ptr/len assignments)
//...
HugeMatrix operator+(const HugeMatrix& , const HugeMatrix& );
HugeMatrix operator+(const HugeMatrix& , HugeMatrix&&);
HugeMatrix operator+( HugeMatrix&&, const HugeMatrix& );
HugeMatrix operator+( HugeMatrix&&, HugeMatrix&&);
//...
hm5 = hm1+hm2+hm3+hm4+hm5; // efficient, no extra copies
#include <memory>
#include <stdexcept>
using namespace std;
// ...
class my_class {
unique_ptr<BigHugeData> data;
public:
my_class( my_class&& other ) // move construction
: data( move( other.data ) ) { }
my_class& operator=( my_class&& other ) // move assignment
{ data = move( other.data ); return *this; }
// ...
void method() { // check (if appropriate)
if( !data )
throw std::runtime_error("RUNTIME ERROR: Insufficient resources!");
}
};
If you enable copy construction/assignment, also enable move construction/assignment if it can be cheaper than
a deep copy.
Some non-value types are move-only, such as when you can’t clone a resource, only transfer ownership.
Example: unique_ptr .
See also
C++ type system
Welcome back to C++
C++ Language Reference
C++ Standard Library
Type conversions and type safety
4/18/2021 • 9 minutes to read • Edit Online
This document identifies common type conversion problems and describes how you can avoid them in your
C++ code.
When you write a C++ program, it's important to ensure that it's type-safe. This means that every variable,
function argument, and function return value is storing an acceptable kind of data, and that operations that
involve values of different types "make sense" and don't cause data loss, incorrect interpretation of bit patterns,
or memory corruption. A program that never explicitly or implicitly converts values from one type to another is
type-safe by definition. However, type conversions, even unsafe conversions, are sometimes required. For
example, you might have to store the result of a floating point operation in a variable of type int , or you might
have to pass the value in an unsigned int to a function that takes a signed int . Both examples illustrate unsafe
conversions because they may cause data loss or re-interpretation of a value.
When the compiler detects an unsafe conversion, it issues either an error or a warning. An error stops
compilation; a warning allows compilation to continue but indicates a possible error in the code. However, even
if your program compiles without warnings, it still may contain code that leads to implicit type conversions that
produce incorrect results. Type errors can also be introduced by explicit conversions, or casts, in the code.
F RO M TO
float double
Notice that values are reinterpreted in both directions. If your program produces odd results in which the sign of
the value seems inverted from what you expect, look for implicit conversions between signed and unsigned
integral types. In the following example, the result of the expression ( 0 - 1) is implicitly converted from int to
unsigned int when it's stored in num . This causes the bit pattern to be reinterpreted.
unsigned int u3 = 0 - 1;
cout << u3 << endl; // prints 4294967295
The compiler doesn't warn about implicit conversions between signed and unsigned integral types. So, we
recommend that you avoid signed-to-unsigned conversions altogether. If you can't avoid them, then add a
runtime check to detect whether the value being converted is greater than or equal to zero and less than or
equal to the maximum value of the signed type. Values in this range will transfer from signed to unsigned or
from unsigned to signed without being reinterpreted.
Pointer conversions
In many expressions, a C-style array is implicitly converted to a pointer to the first element in the array, and
constant conversions can happen silently. Although this is convenient, it's also potentially error-prone. For
example, the following badly designed code example seems nonsensical, and yet it will compile and produces a
result of 'p'. First, the "Help" string constant literal is converted to a char* that points to the first element of the
array; that pointer is then incremented by three elements so that it now points to the last element 'p'.
char* s = "Help" + 3;
The C-style cast operator is identical to the call operator () and is therefore inconspicuous in code and easy to
overlook. Both are bad because they're difficult to recognize at a glance or search for, and they're disparate
enough to invoke any combination of static , const , and reinterpret_cast . Figuring out what an old-style
cast actually does can be difficult and error-prone. For all these reasons, when a cast is required, we recommend
that you use one of the following C++ cast operators, which in some cases are significantly more type-safe, and
which express much more explicitly the programming intent:
static_cast , for casts that are checked at compile time only. static_cast returns an error if the
compiler detects that you are trying to cast between types that are completely incompatible. You can also
use it to cast between pointer-to-base and pointer-to-derived, but the compiler can't always tell whether
such conversions will be safe at runtime.
double d = 1.58947;
int i = d; // warning C4244 possible loss of data
int j = static_cast<int>(d); // No warning.
string s = static_cast<string>(d); // Error C2440:cannot convert from
// double to std:string
//Output: d3 is null;
NOTE
This cast operator isn't used as often as the others, and it's not guaranteed to be portable to other compilers.
The C++ language defines conversions between its fundamental types. It also defines conversions for pointer,
reference, and pointer-to-member derived types. These conversions are called standard conversions.
This section discusses the following standard conversions:
Integral promotions
Integral conversions
Floating conversions
Floating and integral conversions
Arithmetic conversions
Pointer conversions
Reference conversions
Pointer-to-member conversions
NOTE
User-defined types can specify their own conversions. Conversion of user-defined types is covered in Constructors
and Conversions.
The following code causes conversions (in this example, integral promotions):
The result of a conversion is an l-value only if it produces a reference type. For example, a user-defined
conversion declared as operator int&() returns a reference and is an l-value. However, a conversion declared as
operator int() returns an object and isn't an l-value.
Integral promotions
Objects of an integral type can be converted to another wider integral type, that is, a type that can represent a
larger set of values. This widening type of conversion is called integral promotion. With integral promotion, you
can use the following types in an expression wherever another integral type can be used:
Objects, literals, and constants of type char and short int
Enumeration types
int bit fields
Enumerators
C++ promotions are "value-preserving," as the value after the promotion is guaranteed to be the same as the
value before the promotion. In value-preserving promotions, objects of shorter integral types (such as bit fields
or objects of type char ) are promoted to type int if int can represent the full range of the original type. If
int can't represent the full range of values, then the object is promoted to type unsigned int . Although this
strategy is the same as the one used by Standard C, value-preserving conversions don't preserve the
"signedness" of the object.
Value-preserving promotions and promotions that preserve signedness normally produce the same results.
However, they can produce different results if the promoted object appears as:
An operand of / , % , /= , %= , < , <= , > , or >=
These operators rely on sign for determining the result. Value-preserving and sign-preserving
promotions produce different results when applied to these operands.
The left operand of >> or >>=
These operators treat signed and unsigned quantities differently in a shift operation. For signed
quantities, a right shift operation propagates the sign bit into the vacated bit positions, while the vacated
bit positions are zero-filled in unsigned quantities.
An argument to an overloaded function, or the operand of an overloaded operator, that depends on the
signedness of the operand type for argument matching. For more information about defining overloaded
operators, see Overloaded operators.
Integral conversions
Integral conversions are conversions between integral types. The integral types are char , short (or short int
), int , long , and long long . These types may be qualified with signed or unsigned , and unsigned can be
used as shorthand for unsigned int .
Signed to unsigned
Objects of signed integral types can be converted to corresponding unsigned types. When these conversions
occur, the actual bit pattern doesn't change. However, the interpretation of the data changes. Consider this code:
#include <iostream>
In the preceding example, a signed short , i , is defined and initialized to a negative number. The expression
(u = i) causes i to be converted to an unsigned short before the assignment to u .
Unsigned to signed
Objects of unsigned integral types can be converted to corresponding signed types. However, if the unsigned
value is outside the representable range of the signed type, the result won't have the correct value, as
demonstrated in the following example:
#include <iostream>
In the preceding example, u is an unsigned short integral object that must be converted to a signed quantity
to evaluate the expression (i = u) . Because its value can't be properly represented in a signed short , the data
is misinterpreted as shown.
The maximum value representable by type float is 3.402823466E38 — a much smaller number than 1E300.
Therefore, the number is converted to infinity, and the result is "inf".
Arithmetic conversions
Many binary operators (discussed in Expressions with binary operators) cause conversions of operands, and
yield results the same way. The conversions these operators cause are called usual arithmetic conversions.
Arithmetic conversions of operands that have different native types are done as shown in the following table.
Typedef types behave according to their underlying native types.
Conditions for type conversion
C O N DIT IO N S M ET C O N VERSIO N
Either operand is of type long double . Other operand is converted to type long double .
C O N DIT IO N S M ET C O N VERSIO N
Preceding condition not met and either operand is of type Other operand is converted to type double .
double .
Preceding conditions not met and either operand is of type Other operand is converted to type float .
float .
Preceding conditions not met (none of the operands are of Operands get integral promotions as follows:
floating types).
- If either operand is of type unsigned long , the other
operand is converted to type unsigned long .
- If preceding condition not met, and if either operand is of
type long and the other of type unsigned int , both
operands are converted to type unsigned long .
- If the preceding two conditions aren't met, and if either
operand is of type long , the other operand is converted to
type long .
- If the preceding three conditions aren't met, and if either
operand is of type unsigned int , the other operand is
converted to type unsigned int .
- If none of the preceding conditions are met, both operands
are converted to type int .
The following code illustrates the conversion rules described in the table:
double dVal;
float fVal;
int iVal;
unsigned long ulVal;
int main() {
// iVal converted to unsigned long
// result of multiplication converted to double
dVal = iVal * ulVal;
The first statement in the preceding example shows multiplication of two integral types, iVal and ulVal . The
condition met is that neither operand is of floating type, and one operand is of type unsigned int . So, the other
operand, iVal , is converted to type unsigned int . The result is then assigned to dVal . The condition met here
is that one operand is of type double , so the unsigned int result of the multiplication is converted to type
double .
The second statement in the preceding example shows addition of a float and an integral type: fVal and
ulVal . The ulVal variable is converted to type float (third condition in the table). The result of the addition is
converted to type double (second condition in the table) and assigned to dVal .
Pointer conversions
Pointers can be converted during assignment, initialization, comparison, and other expressions.
Pointer to classes
There are two cases in which a pointer to a class can be converted to a pointer to a base class.
The first case is when the specified base class is accessible and the conversion is unambiguous. For more
information about ambiguous base-class references, see Multiple base classes.
Whether a base class is accessible depends on the kind of inheritance used in derivation. Consider the
inheritance illustrated in the following figure.
C O N VERSIO N F RO M
T Y P E O F F UN C T IO N DERIVAT IO N B * TO A* L EGA L?
Protected No
Public Yes
Protected Yes
Public Yes
Protected Yes
Public Yes
The second case in which a pointer to a class can be converted to a pointer to a base class is when you use an
explicit type conversion. For more information about explicit type conversions, see Explicit type conversion
operator.
The result of such a conversion is a pointer to the subobject, the portion of the object that is completely
described by the base class.
The following code defines two classes, A and B , where B is derived from A . (For more information on
inheritance, see Derived Classes.) It then defines bObject , an object of type B , and two pointers ( pA and pB )
that point to the object.
// C2039 expected
class A
{
public:
int AComponent;
int AMemberFunc();
};
class B : public A
{
public:
int BComponent;
int BMemberFunc();
};
int main()
{
B bObject;
A *pA = &bObject;
B *pB = &bObject;
pA->AMemberFunc(); // OK in class A
pB->AMemberFunc(); // OK: inherited from class A
pA->BMemberFunc(); // Error: not in class A
}
The pointer pA is of type A * , which can be interpreted as meaning "pointer to an object of type A ." Members
of bObject (such as BComponent and BMemberFunc ) are unique to type B and are therefore inaccessible
through pA . The pA pointer allows access only to those characteristics (member functions and data) of the
object that are defined in class A .
Pointer to function
A pointer to a function can be converted to type void * , if type void * is large enough to hold that pointer.
Pointer to void
Pointers to type void can be converted to pointers to any other type, but only with an explicit type cast (unlike
in C). A pointer to any type can be converted implicitly to a pointer to type void . A pointer to an incomplete
object of a type can be converted to a pointer to void (implicitly) and back (explicitly). The result of such a
conversion is equal to the value of the original pointer. An object is considered incomplete if it's declared, but
there's insufficient information available to determine its size or base class.
A pointer to any object that is not const or volatile can be implicitly converted to a pointer of type void * .
const and volatile pointers
C++ doesn't supply a standard conversion from a const or volatile type to a type that's not const or
volatile . However, any sort of conversion can be specified using explicit type casts (including conversions that
are unsafe).
NOTE
C++ pointers to members, except pointers to static members, are different from normal pointers and don't have the same
standard conversions. Pointers to static members are normal pointers and have the same conversions as normal pointers.
An expression that results in a function returning a particular type is converted to a pointer to a function
returning that type, except when:
The expression is used as an operand to the address-of operator (& ).
The expression is used as an operand to the function-call operator.
Reference conversions
A reference to a class can be converted to a reference to a base class in these cases:
The specified base class is accessible.
The conversion is unambiguous. (For more information about ambiguous base-class references, see
Multiple base classes.)
The result of the conversion is a pointer to the subobject that represents the base class.
Pointer to member
Pointers to class members can be converted during assignment, initialization, comparison, and other
expressions. This section describes the following pointer-to-member conversions:
Pointer to base class member
A pointer to a member of a base class can be converted to a pointer to a member of a class derived from it,
when the following conditions are met:
The inverse conversion, from pointer to derived class to base-class pointer, is accessible.
The derived class does not inherit virtually from the base class.
When the left operand is a pointer to member, the right operand must be of pointer-to-member type or be a
constant expression that evaluates to 0. This assignment is valid only in the following cases:
The right operand is a pointer to a member of the same class as the left operand.
The left operand is a pointer to a member of a class derived publicly and unambiguously from the class
of the right operand.
null pointer to member conversions
An integral constant expression that evaluates to zero is converted to a null pointer. This pointer always
compares unequal to a pointer to any valid object or function. An exception is pointers to based objects, which
can have the same offset and still point to different objects.
The following code illustrates the definition of a pointer to member i in class A . The pointer, pai , is initialized
to 0, which is the null pointer.
class A
{
public:
int i;
};
int A::*pai = 0;
int main()
{
}
See also
C++ language reference
Built-in types (C++)
3/6/2021 • 5 minutes to read • Edit Online
Built-in types (also called fundamental types) are specified by the C++ language standard and are built into the
compiler. Built-in types aren't defined in any header file. Built-in types are divided into three main categories:
integral, floating-point, and void. Integral types represent whole numbers. Floating-point types can specify
values that may have fractional parts. Most built-in types are treated as distinct types by the compiler. However,
some types are synonyms, or treated as equivalent types by the compiler.
Void type
The void type describes an empty set of values. No variable of type void can be specified. The void type is
used primarily to declare functions that return no values or to declare generic pointers to untyped or arbitrarily
typed data. Any expression can be explicitly converted or cast to type void . However, such expressions are
restricted to the following uses:
An expression statement. (For more information, see Expressions.)
The left operand of the comma operator. (For more information, see Comma Operator.)
The second or third operand of the conditional operator ( ? : ). (For more information, see Expressions
with the Conditional Operator.)
std::nullptr_t
The keyword nullptr is a null-pointer constant of type std::nullptr_t , which is convertible to any raw pointer
type. For more information, see nullptr .
Boolean type
The bool type can have values true and false . The size of the bool type is implementation-specific. See
Sizes of built-in types for Microsoft-specific implementation details.
Character types
The char type is a character representation type that efficiently encodes members of the basic execution
character set. The C++ compiler treats variables of type char , signed char , and unsigned char as having
different types.
Microsoft-specific : Variables of type char are promoted to int as if from type signed char by default,
unless the /J compilation option is used. In this case, they're treated as type unsigned char and are promoted
to int without sign extension.
A variable of type wchar_t is a wide-character or multibyte character type. Use the L prefix before a character
or string literal to specify the wide-character type.
Microsoft-specific : By default, wchar_t is a native type, but you can use /Zc:wchar_t- to make wchar_t a
typedef for unsigned short . The __wchar_t type is a Microsoft-specific synonym for the native wchar_t type.
The char8_t type is used for UTF-8 character representation. It has the same representation as unsigned char ,
but is treated as a distinct type by the compiler. The char8_t type is new in C++20. Microsoft-specific : use of
char8_t requires the /std:c++latest compiler option.
The char16_t type is used for UTF-16 character representation. It must be large enough to represent any UTF-
16 code unit. It's treated as a distinct type by the compiler.
The char32_t type is used for UTF-32 character representation. It must be large enough to represent any UTF-
32 code unit. It's treated as a distinct type by the compiler.
Floating-point types
Floating-point types use an IEEE-754 representation to provide an approximation of fractional values over a
wide range of magnitudes. The following table lists the floating-point types in C++ and the comparative
restrictions on floating-point type sizes. These restrictions are mandated by the C++ standard and are
independent of the Microsoft implementation. The absolute size of built-in floating-point types isn't specified in
the standard.
TYPE C O N T EN T S
long double Type long double is a floating point type that is larger
than or equal to type double .
Microsoft-specific : The representation of long double and double is identical. However, long double and
double are treated as distinct types by the compiler. The Microsoft C++ compiler uses the 4- and 8-byte IEEE-
754 floating-point representations. For more information, see IEEE floating-point representation.
Integer types
The int type is the default basic integer type. It can represent all of the whole numbers over an
implementation-specific range.
A signed integer representation is one that can hold both positive and negative values. It's used by default, or
when the signed modifier keyword is present. The unsigned modifier keyword specifies an unsigned
representation that can only hold non-negative values.
A size modifier specifies the width in bits of the integer representation used. The language supports short ,
long , and long long modifiers. A short type must be at least 16 bits wide. A long type must be at least 32
bits wide. A long long type must be at least 64 bits wide. The standard specifies a size relationship between the
integral types:
1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
An implementation must maintain both the minimum size requirements and the size relationship for each type.
However, the actual sizes can and do vary between implementations. See Sizes of built-in types for Microsoft-
specific implementation details.
The intkeyword may be omitted when signed , unsigned , or size modifiers are specified. The modifiers and
int type, if present, may appear in any order. For example, short unsigned and unsigned int short refer to
the same type.
Integer type synonyms
The following groups of types are considered synonyms by the compiler:
short , short int , signed short , signed short int
long long , long long int , signed long long , signed long long int
Microsoft-specific integer types include the specific-width __int8 , __int16 , __int32 , and __int64 types.
These types may use the signed and unsigned modifiers. The __int8 data type is synonymous with type
char , __int16 is synonymous with type short , __int32 is synonymous with type int , and __int64 is
synonymous with type long long .
TYPE SIZ E
See Data type ranges for a summary of the range of values of each type.
For more information about type conversion, see Standard conversions.
See also
Data type ranges
Data Type Ranges
3/6/2021 • 2 minutes to read • Edit Online
The Microsoft C++ 32-bit and 64-bit compilers recognize the types in the table later in this article.
int ( unsigned int )
__int8 ( unsigned __int8 )
__int16 ( unsigned __int16 )
__int32 ( unsigned __int32 )
__int64 ( unsigned __int64 )
short ( unsigned short )
long ( unsigned long )
long long ( unsigned long long )
If its name begins with two underscores ( __ ), a data type is non-standard.
The ranges that are specified in the following table are inclusive-inclusive.
Depending on how it's used, a variable of __wchar_t designates either a wide-character type or multibyte-
character type. Use the L prefix before a character or string constant to designate the wide-character-type
constant.
signed and are modifiers that you can use with any integral type except bool . Note that char ,
unsigned
signed char , and unsigned char are three distinct types for the purposes of mechanisms like overloading and
templates.
The int and unsigned int types have a size of four bytes. However, portable code should not depend on the
size of int because the language standard allows this to be implementation-specific.
C/C++ in Visual Studio also supports sized integer types. For more information, see
__int8, __int16, __int32, __int64 and Integer Limits.
For more information about the restrictions of the sizes of each type, see Built-in types.
The range of enumerated types varies depending on the language context and specified compiler flags. For
more information, see C Enumeration Declarations and Enumerations.
See also
Keywords
Built-in types
nullptr
3/6/2021 • 2 minutes to read • Edit Online
The nullptr keyword specifies a null pointer constant of type std::nullptr_t , which is convertible to any raw
pointer type. Although you can use the keyword nullptr without including any headers, if your code uses the
type std::nullptr_t , then you must define it by including the header <cstddef> .
NOTE
The nullptr keyword is also defined in C++/CLI for managed code applications and is not interchangeable with the ISO
Standard C++ keyword. If your code might be compiled by using the /clr compiler option, which targets managed
code, then use __nullptr in any line of code where you must guarantee that the compiler uses the native C++
interpretation. For more information, see nullptr (C++/CLI and C++/CX).
Remarks
Avoid using NULL or zero ( 0 ) as a null pointer constant; nullptr is less vulnerable to misuse and works better
in most situations. For example, given func(std::pair<const char *, double>) , then calling
func(std::make_pair(NULL, 3.14)) causes a compiler error. The macro NULL expands to 0 , so that the call
std::make_pair(0, 3.14) returns std::pair<int, double> , which isn't convertible to the
std::pair<const char *, double> parameter type in func . Calling func(std::make_pair(nullptr, 3.14))
successfully compiles because std::make_pair(nullptr, 3.14) returns std::pair<std::nullptr_t, double> ,
which is convertible to std::pair<const char *, double> .
See also
Keywords
nullptr (C++/CLI and C++/CX)
void (C++)
3/6/2021 • 2 minutes to read • Edit Online
When used as a function return type, the void keyword specifies that the function does not return a value.
When used for a function's parameter list, void specifies that the function takes no parameters. When used in
the declaration of a pointer, void specifies that the pointer is "universal."
If a pointer's type is void* , the pointer can point to any variable that is not declared with the const or volatile
keyword. A void* pointer cannot be dereferenced unless it is cast to another type. A void* pointer can be
converted into any other type of data pointer.
A void pointer can point to a function, but not to a class member in C++.
You cannot declare a variable of type void .
Example
// void.cpp
void vobject; // C2182
void *pv; // okay
int *pint; int i;
int main() {
pv = &i;
// Cast optional in C required in C++
pint = (int *)pv;
}
See also
Keywords
Built-in types
bool (C++)
3/6/2021 • 2 minutes to read • Edit Online
This keyword is a built-in type. A variable of this type can have values true and false . Conditional expressions
have the type bool and so have values of type bool . For example, i != 0 now has true or false depending
on the value of i .
Visual Studio 2017 version 15.3 and later (available with /std:c++17): The operand of a postfix or prefix
increment or decrement operator may not be of type bool . In other words, given a variable b of type bool ,
these expressions are no longer allowed:
b++;
++b;
b--;
--b;
!false == true
!true == false
if (condexpr1) statement1;
If condexpr1 is true , statement1 is always executed; if condexpr1 is false , statement1 is never executed.
When a postfix or prefix ++ operator is applied to a variable of type bool , the variable is set to true .
Visual Studio 2017 version 15.3 and later : operator++ for bool was removed from the language and is
no longer supported.
The postfix or prefix -- operator can't be applied to a variable of this type.
The bool type participates in default integral promotions. An r-value of type bool can be converted to an r-
value of type int , with false becoming zero and true becoming one. As a distinct type, bool participates in
overload resolution.
See also
Keywords
Built-in types
false (C++)
3/6/2021 • 2 minutes to read • Edit Online
The keyword is one of the two values for a variable of type bool or a conditional expression (a conditional
expression is now a true Boolean expression). For example, if i is a variable of type bool , the i = false;
statement assigns false to i .
Example
// bool_false.cpp
#include <stdio.h>
int main()
{
bool bb = true;
printf_s("%d\n", bb);
bb = false;
printf_s("%d\n", bb);
}
1
0
See also
Keywords
true (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
bool-identifier = true ;
bool-expression logical-operator true ;
Remarks
This keyword is one of the two values for a variable of type bool or a conditional expression (a conditional
expression is now a true boolean expression). If i is of type bool , then the statement i = true; assigns true
to i .
Example
// bool_true.cpp
#include <stdio.h>
int main()
{
bool bb = true;
printf_s("%d\n", bb);
bb = false;
printf_s("%d\n", bb);
}
1
0
See also
Keywords
char, wchar_t, char8_t, char16_t, char32_t
4/26/2021 • 2 minutes to read • Edit Online
The types char , wchar_t , char8_t , char16_t , and char32_t are built-in types that represent alphanumeric
characters, non-alphanumeric glyphs, and non-printing characters.
Syntax
char ch1{ 'a' }; // or { u8'a' }
wchar_t ch2{ L'a' };
char16_t ch3{ u'a' };
char32_t ch4{ U'a' };
Remarks
The char type was the original character type in C and C++. The char type can be used to store characters
from the ASCII character set or any of the ISO-8859 character sets, and individual bytes of multi-byte characters
such as Shift-JIS or the UTF-8 encoding of the Unicode character set. In the Microsoft compiler, char is an 8-bit
type. It's a distinct type from both signed char and unsigned char . By default, variables of type char get
promoted to int as if from type signed char unless the /J compiler option is used. Under /J , they're
treated as type unsigned char and get promoted to int without sign extension.
The type unsigned char is often used to represent a byte, which isn't a built-in type in C++.
The wchar_t type is an implementation-defined wide character type. In the Microsoft compiler, it represents a
16-bit wide character used to store Unicode encoded as UTF-16LE, the native character type on Windows
operating systems. The wide character versions of the Universal C Runtime (UCRT) library functions use
wchar_t and its pointer and array types as parameters and return values, as do the wide character versions of
the native Windows API.
The char8_t , char16_t , and char32_t types represent 8-bit, 16-bit, and 32-bit wide characters, respectively. (
char8_t is new in C++20 and requires the /std:c++latest compiler option.) Unicode encoded as UTF-8 can be
stored in the char8_t type. Strings of char8_t and char type are referred to as narrow strings, even when
used to encode Unicode or multi-byte characters. Unicode encoded as UTF-16 can be stored in the char16_t
type, and Unicode encoded as UTF-32 can be stored in the char32_t type. Strings of these types and wchar_t
are all referred to as wide strings, though the term often refers specifically to strings of wchar_t type.
In the C++ standard library, the basic_string type is specialized for both narrow and wide strings. Use
std::string when the characters are of type char , std::u8string when the characters are of type char8_t ,
std::u16string when the characters are of type char16_t , std::u32string when the characters are of type
char32_t , and std::wstring when the characters are of type wchar_t . Other types that represent text,
including std::stringstream and std::cout have specializations for narrow and wide strings.
__int8, __int16, __int32, __int64
3/6/2021 • 2 minutes to read • Edit Online
Microsoft-specific
Microsoft C/C++ features support for sized integer types. You can declare 8-, 16-, 32-, or 64-bit integer
variables by using the __intN type specifier, where N is 8, 16, 32, or 64.
The following example declares one variable for each of these types of sized integers:
The types __int8 , __int16 , and __int32 are synonyms for the ANSI types that have the same size, and are
useful for writing portable code that behaves identically across multiple platforms. The __int8 data type is
synonymous with type char , __int16 is synonymous with type short , and __int32 is synonymous with type
int . The __int64 type is synonymous with type long long .
For compatibility with previous versions, _int8 , _int16 , _int32 , and _int64 are synonyms for __int8 ,
__int16 , __int32 , and __int64 unless compiler option /Za (Disable language extensions) is specified.
Example
The following sample shows that an __intN parameter will be promoted to int :
// sized_int_types.cpp
#include <stdio.h>
void func(int i) {
printf_s("%s\n", __FUNCTION__);
}
int main()
{
__int8 i8 = 100;
func(i8); // no void func(__int8 i8) function
// __int8 will be promoted to int
}
func
See also
Keywords
Built-in types
Data Type Ranges
__m64
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __m64 data type is for use with the MMX and 3DNow! intrinsics, and is defined in <xmmintrin.h>.
// data_types__m64.cpp
#include <xmmintrin.h>
int main()
{
__m64 x;
}
Remarks
You should not access the __m64 fields directly. You can, however, see these types in the debugger. A variable of
type __m64 maps to the MM[0-7] registers.
Variables of type _m64 are automatically aligned on 8-byte boundaries.
The __m64 data type is not supported on x64 processors. Applications that use __m64 as part of MMX intrinsics
must be rewritten to use equivalent SSE and SSE2 intrinsics.
END Microsoft Specific
See also
Keywords
Built-in types
Data Type Ranges
__m128
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __m128 data type, for use with the Streaming SIMD Extensions and Streaming SIMD Extensions 2
instructions intrinsics, is defined in <xmmintrin.h>.
// data_types__m128.cpp
#include <xmmintrin.h>
int main() {
__m128 x;
}
Remarks
You should not access the __m128 fields directly. You can, however, see these types in the debugger. A variable of
type __m128 maps to the XMM[0-7] registers.
Variables of type __m128 are automatically aligned on 16-byte boundaries.
The __m128 data type is not supported on ARM processors.
END Microsoft Specific
See also
Keywords
Built-in types
Data Type Ranges
__m128d
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __m128d data type, for use with the Streaming SIMD Extensions 2 instructions intrinsics, is defined in
<emmintrin.h>.
// data_types__m128d.cpp
#include <emmintrin.h>
int main() {
__m128d x;
}
Remarks
You should not access the __m128d fields directly. You can, however, see these types in the debugger. A variable
of type __m128 maps to the XMM[0-7] registers.
Variables of type _m128d are automatically aligned on 16-byte boundaries.
The __m128d data type is not supported on ARM processors.
END Microsoft Specific
See also
Keywords
Built-in types
Data Type Ranges
__m128i
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __m128i data type, for use with the Streaming SIMD Extensions 2 (SSE2) instructions intrinsics, is defined in
<emmintrin.h>.
// data_types__m128i.cpp
#include <emmintrin.h>
int main() {
__m128i x;
}
Remarks
You should not access the __m128i fields directly. You can, however, see these types in the debugger. A variable
of type __m128i maps to the XMM[0-7] registers.
Variables of type __m128i are automatically aligned on 16-byte boundaries.
NOTE
Using variables of type __m128i will cause the compiler to generate the SSE2 movdqa instruction. This instruction does
not cause a fault on Pentium III processors but will result in silent failure, with possible side effects caused by whatever
instructions movdqa translates into on Pentium III processors.
See also
Keywords
Built-in types
Data Type Ranges
__ptr32, __ptr64
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
__ptr32 represents a native pointer on a 32-bit system, while __ptr64 represents a native pointer on a 64-bit
system.
The following example shows how to declare each of these pointer types:
On a 32-bit system, a pointer declared with __ptr64 is truncated to a 32-bit pointer. On a 64-bit system, a
pointer declared with __ptr32 is coerced to a 64-bit pointer.
NOTE
You cannot use __ptr32 or __ptr64 when compiling with /clr :pure . Otherwise, Compiler Error C2472 will be
generated. The /clr :pure and /clr :safe compiler options are deprecated in Visual Studio 2015 and unsupported in Visual
Studio 2017.
For compatibility with previous versions, _ptr32 and _ptr64 are synonyms for __ptr32 and __ptr64 unless
compiler option /Za (Disable language extensions) is specified.
Example
The following example shows how to declare and allocate pointers with the __ptr32 and __ptr64 keywords.
#include <cstdlib>
#include <iostream>
int main()
{
using namespace std;
32
64
The two standard include files, <limits.h> and <float.h>, define the numerical limits, or minimum and maximum
values that a variable of a given type can hold. These minimums and maximums are guaranteed to be portable
to any C++ compiler that uses the same data representation as ANSI C. The <limits.h> include file defines the
numerical limits for integral types, and <float.h> defines the numerical limits for floating types.
See also
Basic Concepts
Integer Limits
3/6/2021 • 2 minutes to read • Edit Online
Microsoft-specific
The limits for integer types are listed in the following table. Preprocessor macros for these limits are also
defined when you include the standard header file <climits>.
CHAR_MAX Maximum value for a variable of type 127; 255 if /J option used
char .
If a value exceeds the largest integer representation, the Microsoft compiler generates an error.
See also
Floating Limits
Floating Limits
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The following table lists the limits on the values of floating-point constants. These limits are also defined in the
standard header file <float.h>.
FLT_GUARD 0
FLT_NORMALIZE 0
NOTE
The information in the table may differ in future versions of the product.
See also
Integer Limits
Declarations and definitions (C++)
3/6/2021 • 4 minutes to read • Edit Online
A C++ program consists of various entities such as variables, functions, types, and namespaces. Each of these
entities must be declared before they can be used. A declaration specifies a unique name for the entity, along
with information about its type and other characteristics. In C++ the point at which a name is declared is the
point at which it becomes visible to the compiler. You cannot refer to a function or class that is declared at some
later point in the compilation unit. Variables should be declared as close as possible before the point at which
they are used.
The following example shows some declarations:
#include <string>
int main()
{
const double pi = 3.14; //OK
int i = f(2); //OK. f is forward-declared
std::string str; // OK std::string is declared in <string> header
C obj; // error! C not yet declared.
j = 0; // error! No type specified.
auto k = 0; // OK. type inferred as int by compiler.
}
int f(int i)
{
return i + 42;
}
namespace N {
class C{/*...*/};
}
On line 5, the main function is declared. On line 7, a const variable named pi is declared and initialized. On
line 8, an integer i is declared and initialized with the value produced by the function f . The name f is
visible to the compiler because of the forward declaration on line 3.
In line 9, a variable named obj of type C is declared. However, this declaration raises an error because C is
not declared until later in the program, and is not forward-declared. To fix the error, you can either move the
entire definition of C before main or else add a forward-declaration for it. This behavior is different from other
languages such as C#, in which functions and classes can be used before their point of declaration in a source
file.
In line 10, a variable named str of type std::string is declared. The name std::string is visible because it is
introduced in the string header file which is merged into the source file in line 1. std is the namespace in
which the string class is declared.
In line 11, an error is raised because the name j has not been declared. A declaration must provide a type,
unlike other languages such as javaScript. In line 12, the auto keyword is used, which tells the compiler to infer
the type of k based on the value that it is initialized with. The compiler in this case chooses int for the type.
Declaration scope
The name that is introduced by a declaration is valid within the scope where the declaration occurs. In the
previous example, the variables that are declared inside the main function are local variables. You could declare
another variable named i outside of main, at global scope, and it would be a completely separate entity.
However, such duplication of names can lead to programmer confusion and errors, and should be avoided. In
line 21, the class C is declared in the scope of the namespace N . The use of namespaces helps to avoid name
collisions. Most C++ Standard Library names are declared within the std namespace. For more information
about how scope rules interact with declarations, see Scope.
Definitions
Some entities, including functions, classes, enums, and constant variables, must be defined in addition to being
declared. A definition provides the compiler with all the information it needs to generate machine code when
the entity is used later in the program. In the previous example, line 3 contains a declaration for the function f
but the definition for the function is provided in lines 15 through 18. On line 21, the class C is both declared
and defined (although as defined the class doesn't do anything). A constant variable must be defined, in other
words assigned a value, in the same statement in which it is declared. A declaration of a built-in type such as
int is automatically a definition because the compiler knows how much space to allocate for it.
extern int i;
char *strchr( const char *Str, const char Target );
extern declarations
A C++ program might contain more than one compilation unit. To declare an entity that is defined in a separate
compilation unit, use the extern keyword. The information in the declaration is sufficient for the compiler, but if
the definition of the entity cannot be found in the linking step, then the linker will raise an error.
In this section
Storage classes
const
constexpr
extern
Initializers
Aliases and typedefs
using declaration
volatile
decltype
Attributes in C++
See also
Basic Concepts
Storage classes
11/2/2020 • 7 minutes to read • Edit Online
A storage class in the context of C++ variable declarations is a type specifier that governs the lifetime, linkage,
and memory location of objects. A given object can have only one storage class. Variables defined within a block
have automatic storage unless otherwise specified using the extern , static , or thread_local specifiers.
Automatic objects and variables have no linkage; they are not visible to code outside the block. Memory is
allocated for them automatically when execution enters the block and de-allocated when the block is exited.
Notes
1. The mutable keyword may be considered a storage class specifier. However, it is only available in the
member list of a class definition.
2. Visual Studio 2010 and later : The auto keyword is no longer a C++ storage-class specifier, and the
register keyword is deprecated. Visual Studio 2017 version 15.7 and later : (available with
/std:c++17 ): The register keyword is removed from the C++ language.
register int val; // warning C5033: 'register' is no longer a supported storage class
static
The static keyword can be used to declare variables and functions at global scope, namespace scope, and
class scope. Static variables can also be declared at local scope.
Static duration means that the object or variable is allocated when the program starts and is deallocated when
the program ends. External linkage means that the name of the variable is visible from outside the file in which
the variable is declared. Conversely, internal linkage means that the name is not visible outside the file in which
the variable is declared. By default, an object or variable that is defined in the global namespace has static
duration and external linkage. The static keyword can be used in the following situations.
1. When you declare a variable or function at file scope (global and/or namespace scope), the static
keyword specifies that the variable or function has internal linkage. When you declare a variable, the
variable has static duration and the compiler initializes it to 0 unless you specify another value.
2. When you declare a variable in a function, the static keyword specifies that the variable retains its state
between calls to that function.
3. When you declare a data member in a class declaration, the static keyword specifies that one copy of
the member is shared by all instances of the class. A static data member must be defined at file scope. An
integral data member that you declare as const static can have an initializer.
4. When you declare a member function in a class declaration, the static keyword specifies that the
function is shared by all instances of the class. A static member function cannot access an instance
member because the function does not have an implicit this pointer. To access an instance member,
declare the function with a parameter that is an instance pointer or reference.
5. You cannot declare the members of a union as static. However, a globally declared anonymous union
must be explicitly declared static .
This example shows how a variable declared static in a function retains its state between calls to that function.
// static1.cpp
// compile with: /EHsc
#include <iostream>
int main() {
for ( int i = 0; i < 5; i++ )
showstat( i );
}
nStatic is 0
nStatic is 1
nStatic is 3
nStatic is 6
nStatic is 10
// static2.cpp
// compile with: /EHsc
#include <iostream>
int CMyClass::m_i = 0;
CMyClass myObject1;
CMyClass myObject2;
int main() {
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
myObject1.m_i = 1;
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
myObject2.m_i = 2;
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
CMyClass::m_i = 3;
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
}
0
0
1
1
2
2
3
3
This example shows a local variable declared static in a member function. The static variable is available to
the whole program; all instances of the type share the same copy of the static variable.
// static3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct C {
void Test(int value) {
static int var = 0;
if (var == value)
cout << "var == value" << endl;
else
cout << "var != value" << endl;
var = value;
}
};
int main() {
C c1;
C c2;
c1.Test(100);
c2.Test(100);
}
var != value
var == value
Starting in C++11, a static local variable initialization is guaranteed to be thread-safe. This feature is
sometimes called magic statics. However, in a multithreaded application all subsequent assignments must be
synchronized. The thread-safe static initialization feature can be disabled by using the /Zc:threadSafeInit- flag
to avoid taking a dependency on the CRT.
extern
Objects and variables declared as extern declare an object that is defined in another translation unit or in an
enclosing scope as having external linkage. For more information, see extern and Translation units and linkage.
thread_local (C++11)
A variable declared with the thread_local specifier is accessible only on the thread on which it is created. The
variable is created when the thread is created, and destroyed when the thread is destroyed. Each thread has its
own copy of the variable. On Windows, thread_local is functionally equivalent to the Microsoft-specific
__declspec( thread ) attribute.
thread_local float f = 42.0; // Global namespace. Not implicitly static.
void DoSomething()
{
// Apply thread_local to a local variable.
// Implicitly "thread_local static S my_struct".
thread_local S my_struct;
}
register
Visual Studio 2017 version 15.3 and later (available with /std:c++17 ): The register keyword is no longer
a supported storage class. The keyword is still reserved in the standard for future use.
register int val; // warning C5033: 'register' is no longer a supported storage class
private:
char *szObjName;
size_t sizeofObjName;
};
Initializing: Auto I1
In block.
Initializing: Auto I2
Initializing: Static I3
Destroying: Auto I2
Exited block.
Destroying: Auto I1
Destroying: Static I3
This example demonstrates how and when the objects I1 , I2 , and I3 are initialized and when they are
destroyed.
There are several points to note about the program:
First, I1 and I2 are automatically destroyed when the flow of control exits the block in which they are
defined.
Second, in C++, it is not necessary to declare objects or variables at the beginning of a block.
Furthermore, these objects are initialized only when the flow of control reaches their definitions. ( I2 and
I3 are examples of such definitions.) The output shows exactly when they are initialized.
Finally, static local variables such as I3 retain their values for the duration of the program, but are
destroyed as the program terminates.
See also
Declarations and Definitions
auto (C++)
3/6/2021 • 7 minutes to read • Edit Online
NOTE
The C++ standard defines an original and a revised meaning for this keyword. Before Visual Studio 2010, the auto
keyword declares a variable in the automatic storage class; that is, a variable that has a local lifetime. Starting with Visual
Studio 2010, the auto keyword declares a variable whose type is deduced from the initialization expression in its
declaration. The /Zc:auto [-] compiler option controls the meaning of the auto keyword.
Syntax
auto declarator initializer ;
Remarks
The auto keyword directs the compiler to use the initialization expression of a declared variable, or lambda
expression parameter, to deduce its type.
We recommend that you use the auto keyword for most situations—unless you really want a conversion—
because it provides these benefits:
Robustness: If the expression’s type is changed—this includes when a function return type is changed—
it just works.
Performance: You’re guaranteed that there will be no conversion.
Usability: You don't have to worry about type name spelling difficulties and typos.
Efficiency: Your coding can be more efficient.
Conversion cases in which you might not want to use auto :
When you want a specific type and nothing else will do.
Expression template helper types—for example, (valarray+valarray) .
To use the auto keyword, use it instead of a type to declare a variable, and specify an initialization expression. In
addition, you can modify the auto keyword by using specifiers and declarators such as const , volatile ,
pointer ( * ), reference ( & ), and rvalue reference ( && ). The compiler evaluates the initialization expression and
then uses that information to deduce the type of the variable.
The auto initialization expression can take several forms:
Universal initialization syntax, such as auto a { 42 }; .
Assignment syntax, such as auto b = 0; .
Universal assignment syntax, which combines the two previous forms, such as auto c = { 3.14156 }; .
Direct initialization, or constructor-style syntax, such as auto d( 1.41421f ); .
For more information, see Initializers and the code examples later in this document.
When auto is used to declare the loop parameter in a range-based for statement, it uses a different
initialization syntax, for example for (auto& i : iterable) do_action(i); . For more information, see Range-
based for Statement (C++).
The auto keyword is a placeholder for a type, but it is not itself a type. Therefore, the auto keyword cannot be
used in casts or operators such as sizeof and (for C++/CLI) typeid .
Usefulness
The autokeyword is a simple way to declare a variable that has a complicated type. For example, you can use
auto to declare a variable where the initialization expression involves templates, pointers to functions, or
pointers to members.
You can also use auto to declare and initialize a variable to a lambda expression. You can't declare the type of
the variable yourself because the type of a lambda expression is known only to the compiler. For more
information, see Examples of Lambda Expressions.
int main( )
{
int count = 10;
int& countRef = count;
auto myAuto = countRef;
countRef = 11;
cout << count << " ";
myAuto = 12;
cout << count << endl;
}
In the previous example, myAuto is an int , not an int reference, so the output is 11 11 , not 11 12 as would
be the case if the reference qualifier had not been dropped by auto .
#include <initializer_list>
int main()
{
// std::initializer_list<int>
auto A = { 1, 2 };
// std::initializer_list<int>
auto B = { 3 };
// int
auto C{ 4 };
return 0;
}
C3537 You cannot cast to a type that is declared with the auto
keyword.
C3538 All the symbols in a declarator list that is declared with the
auto keyword must resolve to the same type. For more
information, see Declarations and Definitions.
ERRO R N UM B ER DESC RIP T IO N
Examples
These code fragments illustrate some of the ways in which the auto keyword can be used.
The following declarations are equivalent. In the first statement, variable j is declared to be type int . In the
second statement, variable k is deduced to be type int because the initialization expression (0) is an integer.
The following declarations are equivalent, but the second declaration is simpler than the first. One of the most
compelling reasons to use the auto keyword is simplicity.
map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();
The following code fragment declares the type of variables iter and elem when the for and range for
loops start.
int main()
{
deque<double> dqDoubleData(10, 0.1);
for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
{ /* ... */ }
The following code fragment uses the new operator and pointer declaration to declare pointers.
double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);
The next code fragment declares multiple symbols in each declaration statement. Notice that all of the symbols
in each statement resolve to the same type.
auto x = 1, *y = &x, **z = &y; // Resolves to int.
auto a(2.01), *b (&a); // Resolves to double.
auto c = 'a', *d(&c); // Resolves to char.
auto m = 1, &n = m; // Resolves to int.
This code fragment uses the conditional operator ( ?: ) to declare variable x as an integer that has a value of
200:
The following code fragment initializes variable x to type int , variable y to a reference to type const int ,
and variable fp to a pointer to a function that returns type int .
See also
Keywords
/Zc:auto (Deduce Variable Type)
sizeof Operator
typeid
operator new
Declarations and Definitions
Examples of Lambda Expressions
Initializers
decltype
const (C++)
3/6/2021 • 3 minutes to read • Edit Online
When modifying a data declaration, the const keyword specifies that the object or variable is not modifiable.
Syntax
const declaration ;
member-function const ;
const values
The const keyword specifies that a variable's value is constant and tells the compiler to prevent the
programmer from modifying it.
// constant_values1.cpp
int main() {
const int i = 5;
i = 10; // C3892
i++; // C2105
}
In C++, you can use the const keyword instead of the #define preprocessor directive to define constant values.
Values defined with const are subject to type checking, and can be used in place of constant expressions. In
C++, you can specify the size of an array with a const variable as follows:
// constant_values2.cpp
// compile with: /c
const int maxarray = 255;
char store_char[maxarray]; // allowed in C++; not allowed in C
In C, constant values default to external linkage, so they can appear only in source files. In C++, constant values
default to internal linkage, which allows them to appear in header files.
The const keyword can also be used in pointer declarations.
// constant_values3.cpp
int main() {
char *mybuf = 0, *yourbuf;
char *const aptr = mybuf;
*aptr = 'a'; // OK
aptr = yourbuf; // C3892
}
A pointer to a variable declared as const can be assigned only to a pointer that is also declared as const .
// constant_values4.cpp
#include <stdio.h>
int main() {
const char *mybuf = "test";
char *yourbuf = "test2";
printf_s("%s\n", mybuf);
You can use pointers to constant data as function parameters to prevent the function from modifying a
parameter passed through a pointer.
For objects that are declared as const , you can only call constant member functions. This ensures that the
constant object is never modified.
birthday.getMonth(); // Okay
birthday.setMonth( 4 ); // Error
You can call either constant or nonconstant member functions for a nonconstant object. You can also overload a
member function using the const keyword; this allows a different version of the function to be called for
constant and nonconstant objects.
You cannot declare constructors or destructors with the const keyword.
const int i = 2;
But to get the same behavior in C++, you must declare your const variable as:
If you wish to declare an extern variable in a C++ source code file for use in a C source code file, use:
Remarks
When following a member function's parameter list, the const keyword specifies that the function does not
modify the object for which it is invoked.
For more information on const , see the following topics:
const and volatile Pointers
Type Qualifiers (C Language Reference)
volatile
#define
See also
Keywords
constexpr (C++)
11/2/2020 • 5 minutes to read • Edit Online
The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like
const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value.
Unlike const , constexpr can also be applied to functions and class constructors. constexpr indicates that the
value, or return value, is constant and, where possible, is computed at compile time.
A constexpr integral value can be used wherever a const integer is required, such as in template arguments and
array declarations. And when a value is computed at compile time instead of run time, it helps your program run
faster and use less memory.
To limit the complexity of compile-time constant computations, and their potential impacts on compilation time,
the C++14 standard requires the types in constant expressions to be literal types.
Syntax
constexpr literal-type identifier = constant-expression ;
constexpr literal-type identifier { constant-expression } ;
constexpr literal-type identifier ( params ) ;
constexpr ctor ( params ) ;
Parameters
params
One or more parameters, each of which must be a literal type and must itself be a constant expression.
Return value
A constexpr variable or function must return a literal type.
constexpr variables
The primary difference between const and constexpr variables is that the initialization of a const variable can
be deferred until run time. A constexpr variable must be initialized at compile time. All constexpr variables are
const .
A variable can be declared with constexpr , when it has a literal type and is initialized. If the initialization
is performed by a constructor, the constructor must be declared as constexpr .
A reference may be declared as constexpr when both these conditions are met: The referenced object is
initialized by a constant expression, and any implicit conversions invoked during initialization are also
constant expressions.
All declarations of a constexpr variable or function must have the constexpr specifier.
constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression
constexpr functions
A constexpr function is one whose return value is computable at compile time when consuming code requires
it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a
non-type template argument. When its arguments are constexpr values, a constexpr function produces a
compile-time constant. When called with non- constexpr arguments, or when its value isn't required at compile
time, it produces a value at run time like a regular function. (This dual behavior saves you from having to write
constexpr and non- constexpr versions of the same function.)
The following rules apply to constexpr functions in Visual Studio 2017 and later:
It may contain if and switch statements, and all looping statements including for , range-based for ,
while , and do-while .
It may contain local variable declarations, but the variable must be initialized. It must be a literal type, and
can't be static or thread-local. The locally declared variable isn't required to be const , and may mutate.
A constexpr non- static member function isn't required to be implicitly const .
TIP
In the Visual Studio debugger, when debugging a non-optimised Debug build, you can tell whether a constexpr
function is being evaluated at compile time by putting a breakpoint inside it. If the breakpoint is hit, the function was
called at run-time. If not, then the function was called at compile time.
extern constexpr
The /Zc:externConstexpr compiler option causes the compiler to apply external linkage to variables declared by
using extern constexpr . In earlier versions of Visual Studio, either by default or when /Zc:externConstexpr-
is specified, Visual Studio applies internal linkage to constexpr variables even when the extern keyword is
used. The /Zc:externConstexpr option is available starting in Visual Studio 2017 Update 15.6, and is off by
default. The /permissive- option doesn't enable /Zc:externConstexpr .
Example
The following example shows constexpr variables, functions, and a user-defined type. In the last statement in
main() , the constexpr member function GetValue() is a run-time call because the value isn't required to be
known at compile time.
// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>
// Pass by value
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp2(x * x, n / 2) :
exp2(x * x, (n - 1) / 2) * x;
}
// User-defined type
class Foo
{
public:
constexpr explicit Foo(int i) : _i(i) {}
constexpr int GetValue() const
{
return _i;
}
private:
int _i;
};
int main()
{
// foo is const:
constexpr Foo foo(5);
// foo = Foo(6); //Error!
// Compile time:
constexpr float x = exp(5, 3);
constexpr float y { exp(2, 5) };
constexpr int val = foo.GetValue();
constexpr int f5 = fac(5);
const int nums[] { 1, 2, 3, 4 };
const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };
// Run time:
cout << "The value of foo is " << foo.GetValue() << endl;
}
Requirements
Visual Studio 2015 or later.
See also
Declarations and definitions
const
extern (C++)
11/2/2020 • 4 minutes to read • Edit Online
The extern keyword may be applied to a global variable, function, or template declaration. It specifies that the
symbol has external linkage. For background information on linkage and why the use of global variables is
discouraged, see Translation units and linkage.
The extern keyword has four meanings depending on the context:
In a non- const global variable declaration, extern specifies that the variable or function is defined in
another translation unit. The extern must be applied in all files except the one where the variable is
defined.
In a const variable declaration, it specifies that the variable has external linkage. The extern must be
applied to all declarations in all files. (Global const variables have internal linkage by default.)
extern "C" specifies that the function is defined elsewhere and uses the C-language calling convention.
The extern "C" modifier may also be applied to multiple function declarations in a block.
In a template declaration, extern specifies that the template has already been instantiated elsewhere.
extern tells the compiler it can reuse the other instantiation, rather than create a new one at the current
location. For more information about this use of extern , see Explicit instantiation.
//fileA.cpp
int i = 42; // declaration and definition
//fileB.cpp
extern int i; // declaration only. same as i in FileA
//fileC.cpp
extern int i; // declaration only. same as i in FileA
//fileD.cpp
int i = 43; // LNK2005! 'i' already has a definition.
extern int i = 43; // same error (extern is ignored on definitions)
//fileA.cpp
extern const int i = 42; // extern const definition
//fileB.cpp
extern const int i; // declaration only. same as i in FileA
extern constexpr linkage
In Visual Studio 2017 version 15.3 and earlier, the compiler always gave a constexpr variable internal linkage,
even when the variable was marked extern . In Visual Studio 2017 version 15.5 and later, the
/Zc:externConstexpr compiler switch enables correct standards-conforming behavior. Eventually the option will
become the default. The /permissive- option doesn't enable /Zc:externConstexpr .
extern constexpr int x = 10; //error LNK2005: "int const x" already defined
If a header file contains a variable declared extern constexpr , it must be marked __declspec(selectany) to
correctly have its duplicate declarations combined:
Example
The following example shows how to declare names that have C linkage:
// Declare printf with C linkage.
extern "C" int printf(const char *fmt, ...);
If a function has more than one linkage specification, they must agree. It's an error to declare functions as having
both C and C++ linkage. Furthermore, if two declarations for a function occur in a program — one with a
linkage specification and one without — the declaration with the linkage specification must be first. Any
redundant declarations of functions that already have linkage specification are given the linkage specified in the
first declaration. For example:
int CFunc2();
...
extern "C" int CFunc2(); // Error: not the first declaration of
// CFunc2; cannot contain linkage
// specifier.
See also
Keywords
Translation units and linkage
extern Storage-Class Specifier in C
Behavior of Identifiers in C
Linkage in C
Initializers
11/2/2020 • 12 minutes to read • Edit Online
An initializer specifies the initial value of a variable. You can initialize variables in these contexts:
In the definition of a variable:
int i = 3;
Point p1{ 1, 2 };
set_point(Point{ 5, 6 });
string s = "hello";
A braced initializer list. The list may be empty or may consist of a set of lists, as in the following example:
struct Point{
int x;
int y;
};
class PointConsumer{
public:
void set_point(Point p){};
void set_points(initializer_list<Point> my_list){};
};
int main() {
PointConsumer pc{};
pc.set_point({});
pc.set_point({ 3, 4 });
pc.set_points({ { 3, 4 }, { 5, 6 } });
}
Kinds of initialization
There are several kinds of initialization, which may occur at different points in program execution. Different
kinds of initialization are not mutually exclusive—for example, list initialization can trigger value initialization
and in other circumstances, it can trigger aggregate initialization.
Zero initialization
Zero initialization is the setting of a variable to a zero value implicitly converted to the type:
Numeric variables are initialized to 0 (or 0.0, or 0.0000000000, etc.).
Char variables are initialized to '\0' .
Pointers are initialized to nullptr .
Arrays, POD classes, structs, and unions have their members initialized to a zero value.
Zero initialization is performed at different times:
At program startup, for all named variables that have static duration. These variables may later be
initialized again.
During value initialization, for scalar types and POD class types that are initialized by using empty braces.
For arrays that have only a subset of their members initialized.
Here are some examples of zero initialization:
struct my_struct{
int i;
char c;
};
Default initialization
Default initialization for classes, structs, and unions is initialization with a default constructor. The default
constructor can be called with no initialization expression or with the new keyword:
MyClass mc1;
MyClass* mc3 = new MyClass;
If the class, struct, or union does not have a default constructor, the compiler emits an error.
Scalar variables are default initialized when they are defined with no initialization expression. They have
indeterminate values.
int i1;
float f;
char c;
Arrays are default initialized when they are defined with no initialization expression. When an array is default-
initialized, its members are default initialized and have indeterminate values, as in the following example:
int int_arr[3];
If the array members do not have a default constructor, the compiler emits an error.
Default initialization of constant variables
Constant variables must be declared together with an initializer. If they are scalar types they cause a compiler
error, and if they are class types that have a default constructor they cause a warning:
class MyClass{};
int main() {
//const int i2; // compiler error C2734: const object must be initialized if not extern
//const char c2; // same error
const MyClass mc1; // compiler error C4269: 'const automatic data initialized with compiler generated
default constructor produces unreliable results
}
class MyClass {
private:
int m_int;
char m_char;
};
int main() {
static int int1; // 0
static char char1; // '\0'
static bool bool1; // false
static MyClass mc1; // {0, '\0'}
}
For more information about initialization of global static objects, see main function and command-line
arguments.
Value initialization
Value initialization occurs in the following cases:
a named value is initialized using empty brace initialization
an anonymous temporary object is initialized using empty parentheses or braces
an object is initialized with the new keyword plus empty parentheses or braces
Value initialization does the following:
for classes with at least one public constructor, the default constructor is called
for non-union classes with no declared constructors, the object is zero-initialized and the default
constructor is called
for arrays, every element is value-initialized
in all other cases, the variable is zero initialized
class BaseClass {
private:
int m_int;
};
int main() {
BaseClass bc{}; // class is initialized
BaseClass* bc2 = new BaseClass(); // class is initialized, m_int value is 0
int int_arr[3]{}; // value of all members is 0
int a{}; // value of a is 0
double b{}; // value of b is 0.00000000000000000
}
Copy initialization
Copy initialization is the initialization of one object using a different object. It occurs in the following cases:
a variable is initialized using an equals sign
an argument is passed to a function
an object is returned from a function
an exception is thrown or caught
a non-static data member is initialized using an equals sign
class, struct, and union members are initialized by copy initialization during aggregate initialization. See
Aggregate initialization for examples.
The following code shows several examples of copy initialization:
#include <iostream>
using namespace std;
class MyClass{
public:
MyClass(int myInt) {}
void set_int(int myInt) { m_int = myInt; }
int get_int() const { return m_int; }
private:
int m_int = 7; // copy initialization of m_int
};
class MyException : public exception{};
int main() {
int i = 5; // copy initialization of i
MyClass mc1{ i };
MyClass mc2 = mc1; // copy initialization of mc2 from mc1
MyClass mc1.set_int(i); // copy initialization of parameter from i
int i2 = mc2.get_int(); // copy initialization of i2 from return value of get_int()
try{
throw MyException();
}
catch (MyException ex){ // copy initialization of ex
cout << ex.what();
}
}
In some cases, if the copy constructor of the class is deleted or inaccessible, copy initialization causes a compiler
error.
Direct initialization
Direct initialization is initialization using (non-empty) braces or parentheses. Unlike copy initialization, it can
invoke explicit constructors. It occurs in the following cases:
a variable is initialized with non-empty braces or parentheses
a variable is initialized with the new keyword plus non-empty braces or parentheses
a variable is initialized with static_cast
in a constructor, base classes and non-static members are initialized with an initializer list
in the copy of a captured variable inside a lambda expression
The following code shows some examples of direct initialization:
class BaseClass{
public:
BaseClass(int n) :m_int(n){} // m_int is direct initialized
private:
int m_int;
};
int a = 1;
function<int()> func = [a](){ return a + 1; }; // a is direct initialized
int n = func();
}
List initialization
List initialization occurs when a variable is initialized using a braced initializer list. Braced initializer lists can be
used in the following cases:
a variable is initialized
a class is initialized with the new keyword
an object is returned from a function
an argument passed to a function
one of the arguments in a direct initialization
in a non-static data member initializer
in a constructor initializer list
The following code shows some examples of list initialization:
class MyClass {
public:
MyClass(int myInt, char myChar) {}
private:
int m_int[]{ 3 };
char m_char;
};
class MyClassConsumer{
public:
void set_class(MyClass c) {}
MyClass get_class() { return MyClass{ 0, '\0' }; }
};
struct MyStruct{
int my_int;
char my_char;
MyClass my_class;
};
int main() {
MyClass mc1{ 1, 'a' };
MyClass* mc2 = new MyClass{ 2, 'b' };
MyClass mc3 = { 3, 'c' };
MyClassConsumer mcc;
mcc.set_class(MyClass{ 3, 'c' });
mcc.set_class({ 4, 'd' });
Aggregate initialization
Aggregate initialization is a form of list initialization for arrays or class types (often structs or unions) that have:
no private or protected members
no user-provided constructors, except for explicitly defaulted or deleted constructors
no base classes
no virtual member functions
NOTE
In Visual Studio 2015 and earlier, an aggregate is not allowed to have brace-or-equal initializers for non-static members. This
restriction was removed in the C++14 standard and implemented in Visual Studio 2017.
Aggregate initializers consist of a braced initialization list, with or without an equals sign, as in the following
example:
#include <iostream>
using namespace std;
struct MyAggregate{
int myInt;
char myChar;
};
struct MyAggregate2{
int myInt;
char myChar = 'Z'; // member-initializer OK in C++14
};
int main() {
MyAggregate agg1{ 1, 'c' };
MyAggregate2 agg2{2};
cout << "agg1: " << agg1.myChar << ": " << agg1.myInt << endl;
cout << "agg2: " << agg2.myChar << ": " << agg2.myInt << endl;
int myArr1[]{ 1, 2, 3, 4 };
int myArr2[3] = { 5, 6, 7 };
int myArr3[5] = { 8, 9, 10 };
agg1: c: 1
agg2: Z: 2
myArr1: 1 2 3 4
myArr3: 8 9 10 0 0
IMPORTANT
Array members that are declared but not explicitly initialized during aggregate initialization are zero-initialized, as in
myArr3 above.
int main() {
MyUnion mu1{ 'a' }; // my_int = 97, my_char = 'a', my_bool = true, {myInt = 97, myChar = '\0'}
MyUnion mu2{ 1 }; // my_int = 1, my_char = 'x1', my_bool = true, {myInt = 1, myChar = '\0'}
MyUnion mu3{}; // my_int = 0, my_char = '\0', my_bool = false, {myInt = 0, myChar = '\0'}
MyUnion mu4 = mu3; // my_int = 0, my_char = '\0', my_bool = false, {myInt = 0, myChar = '\0'}
//MyUnion mu5{ 1, 'a', true }; // compiler error: C2078: too many initializers
//MyUnion mu6 = 'a'; // compiler error: C2440: cannot convert from 'char' to 'MyUnion'
//MyUnion mu7 = 1; // compiler error: C2440: cannot convert from 'int' to 'MyUnion'
struct MyStruct {
int myInt;
char myChar;
};
int main() {
int intArr1[2][2]{{ 1, 2 }, { 3, 4 }};
int intArr3[2][2] = {1, 2, 3, 4};
MyStruct structArr[]{ { 1, 'a' }, { 2, 'b' }, {3, 'c'} };
}
Reference initialization
Variables of reference type must be initialized with an object of the type from which the reference type is
derived, or with an object of a type that can be converted to the type from which the reference type is derived.
For example:
// initializing_references.cpp
int iVar;
long lVar;
int main()
{
long& LongRef1 = lVar; // No conversion required.
long& LongRef2 = iVar; // Error C2440
const long& LongRef3 = iVar; // OK
LongRef1 = 23L; // Change lVar through a reference.
LongRef2 = 11L; // Change iVar through a reference.
LongRef3 = 11L; // Error C3892
}
The only way to initialize a reference with a temporary object is to initialize a constant temporary object. Once
initialized, a reference-type variable always points to the same object; it cannot be modified to point to another
object.
Although the syntax can be the same, initialization of reference-type variables and assignment to reference-type
variables are semantically different. In the preceding example, the assignments that change iVar and lVar
look similar to the initializations, but have different effects. The initialization specifies the object to which the
reference-type variable points; the assignment assigns to the referred-to object through the reference.
Because both passing an argument of reference type to a function and returning a value of reference type from
a function are initializations, the formal arguments to a function are initialized correctly, as are the references
returned.
Reference-type variables can be declared without initializers only in the following:
Function declarations (prototypes). For example:
When initializing a reference-type variable, the compiler uses the decision graph shown in the following figure
to select between creating a reference to an object or creating a temporary object to which the reference points.
You can use an alias declaration to declare a name to use as a synonym for a previously declared type. (This
mechanism is also referred to informally as a type alias). You can also use this mechanism to create an alias
template, which can be particularly useful for custom allocators.
Syntax
using identifier = type;
Remarks
identifier
The name of the alias.
type
The type identifier you are creating an alias for.
An alias does not introduce a new type and cannot change the meaning of an existing type name.
The simplest form of an alias is equivalent to the typedef mechanism from C++03:
// C++11
using counter = long;
// C++03 equivalent:
// typedef long counter;
Both of these enable the creation of variables of type "counter". Something more useful would be a type alias
like this one for std::ios_base::fmtflags :
// C++11
using fmtfl = std::ios_base::fmtflags;
// C++03 equivalent:
// typedef std::ios_base::fmtflags fmtfl;
Aliases also work with function pointers, but are much more readable than the equivalent typedef:
// C++11
using func = void(*)(int);
// C++03 equivalent:
// typedef void (*func)(int);
A limitation of the typedef mechanism is that it doesn't work with templates. However, the type alias syntax in
C++11 enables the creation of alias templates:
Example
The following example demonstrates how to use an alias template with a custom allocator—in this case, an
integer vector type. You can substitute any type for int to create a convenient alias to hide the complex
parameter lists in your main functional code. By using the custom allocator throughout your code you can
improve readability and reduce the risk of introducing bugs caused by typos.
#include <stdlib.h>
#include <new>
MyAlloc() { }
template <typename U> MyAlloc(const MyAlloc<U>&) { }
if (!pv) {
throw std::bad_alloc();
}
#include <vector>
using MyIntVector = std::vector<int, MyAlloc<int>>;
#include <iostream>
int main ()
{
MyIntVector foov = { 1701, 1764, 1664 };
return 0;
}
Typedefs
A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the
type-declaration portion of the declaration.
You can use typedef declarations to construct shorter or more meaningful names for types already defined by
the language or for types that you have declared. Typedef names allow you to encapsulate implementation
details that may change.
In contrast to the class , struct , union , and enum declarations, typedef declarations do not introduce new
types — they introduce new names for existing types.
Names declared using typedef occupy the same namespace as other identifiers (except statement labels).
Therefore, they cannot use the same identifier as a previously declared name, except in a class-type declaration.
Consider the following example:
// typedef_names1.cpp
// C2377 expected
typedef unsigned long UL; // Declare a typedef name, UL.
int UL; // C2377: redefined.
The name-hiding rules that pertain to other identifiers also govern the visibility of names declared using
typedef . Therefore, the following example is legal in C++:
// typedef_names2.cpp
typedef unsigned long UL; // Declare a typedef name, UL
int main()
{
unsigned int UL; // Redeclaration hides typedef name
}
// typedef_specifier1.cpp
typedef char FlagType;
int main()
{
}
When declaring a local-scope identifier by the same name as a typedef, or when declaring a member of a
structure or union in the same scope or in an inner scope, the type specifier must be specified. For example:
To reuse the FlagType name for an identifier, a structure member, or a union member, the type must be
provided:
because the FlagType is taken to be part of the type, not an identifier that is being redeclared. This declaration is
taken to be an illegal declaration like
int; // Illegal declaration
You can declare any type with typedef, including pointer, function, and array types. You can declare a typedef
name for a pointer to a structure or union type before you define the structure or union type, as long as the
definition has the same visibility as the declaration.
Examples
One use of typedef declarations is to make declarations more uniform and compact. For example:
To use typedef to specify fundamental and derived types in the same declaration, you can separate declarators
with commas. For example:
The following example provides the type DRAWF for a function returning no value and taking two int arguments:
DRAWF box;
typedef is often combined with struct to declare and name user-defined types:
// typedef_specifier2.cpp
#include <stdio.h>
int main()
{
mystruct ms;
ms.i = 10;
ms.f = 0.99;
printf_s("%d %f\n", ms.i, ms.f);
}
10 0.990000
Re -declaration of typedefs
The typedef declaration can be used to redeclare the same name to refer to the same type. For example:
// FILE1.H
typedef char CHAR;
// FILE2.H
typedef char CHAR;
// PROG.CPP
#include "file1.h"
#include "file2.h" // OK
The program PROG.CPP includes two header files, both of which contain typedef declarations for the name
CHAR . As long as both declarations refer to the same type, such redeclaration is acceptable.
A typedef cannot redefine a name that was previously declared as a different type. Therefore, if FILE2.H
contains
// FILE2.H
typedef int CHAR; // Error
the compiler issues an error because of the attempt to redeclare the name CHAR to refer to a different type. This
extends to constructs such as:
// typedef_with_class_types1.cpp
// compile with: /c
typedef struct { // Declare an unnamed structure and give it the
// typedef name POINT.
unsigned x;
unsigned y;
} POINT;
POINT ptOrigin;
instead of:
// typedef_with_class_types2.cpp
// compile with: /c /W1
typedef struct {
int POINT();
unsigned x;
unsigned y;
} POINT;
The preceding example declares a class named POINT using the unnamed class typedef syntax. POINT is
treated as a class name; however, the following restrictions apply to names introduced this way:
The name (the synonym) cannot appear after a class , struct , or union prefix.
The name cannot be used as constructor or destructor names within a class declaration.
In summary, this syntax does not provide any mechanism for inheritance, construction, or destruction.
using declaration
3/6/2021 • 5 minutes to read • Edit Online
The using declaration introduces a name into the declarative region in which the using declaration appears.
Syntax
using [typename] nested-name-specifier unqualified-id ;
using declarator-list ;
Parameters
nested-name-specifier A sequence of namespace, class, or enumeration names and scope resolution operators
(::), terminated by a scope resolution operator. A single scope resolution operator may be used to introduce a
name from the global namespace. The keyword typename is optional and may be used to resolve dependent
names when introduced into a class template from a base class.
unqualified-id An unqualified id-expression, which may be an identifier, an overloaded operator name, a user-
defined literal operator or conversion function name, a class destructor name, or a template name and
argument list.
declarator-list A comma-separated list of [ typename ] nested-name-specifier unqualified-id declarators, followed
optionally by an ellipsis.
Remarks
A using declaration introduces an unqualified name as a synonym for an entity declared elsewhere. It allows a
single name from a specific namespace to be used without explicit qualification in the declaration region in
which it appears. This is in contrast to the using directive, which allows all the names in a namespace to be used
without qualification. The using keyword is also used for type aliases.
void g(char) {
printf_s("In B::g()\n");
}
};
class D : B {
public:
using B::f; // B::f(char) is now visible as D::f(char)
using B::g; // B::g(char) is now visible as D::g(char)
void f(int) {
printf_s("In D::f()\n");
f('c'); // Invokes B::f(char) instead of recursing
}
void g(int) {
printf_s("In D::g()\n");
g('c'); // Invokes B::g(char) instead of recursing
}
};
int main() {
D myD;
myD.f(1);
myD.g('a');
}
In D::f()
In B::f()
In B::g()
class B {
public:
void f(char) {
printf_s("In B::f()\n");
}
void g(char) {
printf_s("In B::g()\n");
}
};
class C {
public:
int g();
};
class D2 : public B {
public:
using B::f; // ok: B is a base of D2
// using C::g; // error: C isn't a base of D2
};
int main() {
D2 MyD2;
MyD2.f('a');
}
In B::f()
void f() {
printf_s("In f\n");
}
namespace A {
void g() {
printf_s("In A::g\n");
}
}
namespace X {
using ::f; // global f is also visible as X::f
using A::g; // A's g is now visible as X::g
}
void h() {
printf_s("In h\n");
X::f(); // calls ::f
X::g(); // calls A::g
}
int main() {
h();
}
In h
In f
In A::g
namespace A {
void f(char) {}
}
void f() {
f('a'); // refers to A::f(int), even though A::f(char) exists
}
void b() {
using A::f; // refers to A::f(int) AND A::f(char)
f('a'); // calls A::f(char);
}
// functions_in_namespaces1.cpp
// C2874 expected
namespace B {
int i;
void f(int);
void f(double);
}
void g() {
int i;
using B::i; // error: i declared twice
void f(char);
using B::f; // ok: each f is a function
}
In the example above, the using B::i statement causes a second int i to be declared in the g() function.
The using B::f statement does not conflict with the f(char) function because the function names introduced
by B::f have different parameter types.
namespace C {
void f(int);
void f(double);
void f(char);
}
void h() {
using B::f; // introduces B::f(int) and B::f(double)
using C::f; // C::f(int), C::f(double), and C::f(char)
f('h'); // calls C::f(char)
f(1); // C2668 ambiguous: B::f(int) or C::f(int)?
void f(int); // C2883 conflicts with B::f(int) and C::f(int)
}
void g(int) {
printf_s("In B::g\n");
}
void h(int);
};
struct D : B {
using B::f;
void f(int) { // ok: D::f(int) overrides B::f(int)
printf_s("In D::f(int)\n");
}
using B::g;
void g(char) { // ok: there is no B::g(char)
printf_s("In D::g(char)\n");
}
using B::h;
void h(int) {} // Note: D::h(int) hides non-virtual B::h(int)
};
int main() {
D * myd = new D();
f(myd);
}
In D::f(int)
In B::f(char)
In B::g
In D::g(char)
class B : public A {
using A::f; // C2876: A::f(char) is inaccessible
public:
using A::g; // B::g is a public synonym for A::g
};
See also
Namespaces
Keywords
volatile (C++)
3/6/2021 • 3 minutes to read • Edit Online
A type qualifier that you can use to declare that an object can be modified in the program by the hardware.
Syntax
volatile declarator ;
Remarks
You can use the /volatile compiler switch to modify how the compiler interprets this keyword.
Visual Studio interprets the volatile keyword differently depending on the target architecture. For ARM, if no
/volatile compiler option is specified, the compiler performs as if /volatile:iso were specified. For architectures
other than ARM, if no /volatile compiler option is specified, the compiler performs as if /volatile:ms were
specified; therefore, for architectures other than ARM we strongly recommend that you specify /volatile:iso ,
and use explicit synchronization primitives and compiler intrinsics when you are dealing with memory that is
shared across threads.
You can use the volatile qualifier to provide access to memory locations that are used by asynchronous
processes such as interrupt handlers.
When volatile is used on a variable that also has the __restrict keyword, volatile takes precedence.
If a struct member is marked as volatile , then volatile is propagated to the whole structure. If a structure
does not have a length that can be copied on the current architecture by using one instruction, volatile may
be completely lost on that structure.
The volatile keyword may have no effect on a field if one of the following conditions is true:
The length of the volatile field exceeds the maximum size that can be copied on the current architecture
by using one instruction.
The length of the outermost containing struct —or if it's a member of a possibly nested struct —
exceeds the maximum size that can be copied on the current architecture by using one instruction.
Although the processor does not reorder un-cacheable memory accesses, un-cacheable variables must be
marked as volatile to guarantee that the compiler does not reorder the memory accesses.
Objects that are declared as volatile are not used in certain optimizations because their values can change at
any time. The system always reads the current value of a volatile object when it is requested, even if a previous
instruction asked for a value from the same object. Also, the value of the object is written immediately on
assignment.
ISO Compliant
If you are familiar with the C# volatile keyword, or familiar with the behavior of volatile in earlier versions of
the Microsoft C++ compiler (MSVC), be aware that the C++11 ISO Standard volatile keyword is different and
is supported in MSVC when the /volatile:iso compiler option is specified. (For ARM, it's specified by default). The
volatile keyword in C++11 ISO Standard code is to be used only for hardware access; do not use it for inter-
thread communication. For inter-thread communication, use mechanisms such as std::atomic<T> from the C++
Standard Library.
NOTE
When it relies on the enhanced guarantee that's provided when the /volatile:ms compiler option is used, the code is
non-portable.
See also
Keywords
const
const and volatile Pointers
decltype (C++)
3/6/2021 • 5 minutes to read • Edit Online
The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with
the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to
declare a template function whose return type depends on the types of its template arguments. Or, use auto
and decltype to declare a template function that wraps a call to another function, and then returns the return
type of the wrapped function.
Syntax
decltype( expression )
Parameters
expression
An expression. For more information, see Expressions.
Return Value
The type of the expression parameter.
Remarks
The decltype type specifier is supported in Visual Studio 2010 or later versions, and can be used with native or
managed code. decltype(auto) (C++14) is supported in Visual Studio 2015 and later.
The compiler uses the following rules to determine the type of the expression parameter.
If the expression parameter is an identifier or a class member access, decltype(expression) is the type of
the entity named by expression. If there is no such entity or the expression parameter names a set of
overloaded functions, the compiler yields an error message.
If the expression parameter is a call to a function or an overloaded operator function,
decltype(expression) is the return type of the function. Parentheses around an overloaded operator are
ignored.
If the expression parameter is an rvalue, decltype(expression) is the type of expression. If the expression
parameter is an lvalue, decltype(expression) is an lvalue reference to the type of expression.
The following code example demonstrates some uses of the decltype type specifier. First, assume that you have
coded the following statements.
int var;
const int&& fx();
struct A { double x; }
const A* a = new A();
Next, examine the types that are returned by the four decltype statements in the following table.
STAT EM EN T TYPE N OT ES
The introduction of the decltype type specifier enables a developer to obtain the type of the expression that the
template function returns. Use the alternative function declaration syntax that is shown later, the auto keyword,
and the decltype type specifier to declare a late-specified return type. The late-specified return type is
determined when the declaration is compiled, instead of when it is coded.
The following prototype illustrates the syntax of an alternative function declaration. Note that the const and
volatile qualifiers, and the throw exception specification are optional. The function_body placeholder
represents a compound statement that specifies what the function does. As a best coding practice, the
expression placeholder in the decltype statement should match the expression specified by the return
statement, if any, in the function_body.
auto function_name ( parametersopt ) const opt volatile opt -> decltype( expression ) noexcept opt
{ function_body };
In the following code example, the late-specified return type of the myFunc template function is determined by
the types of the t and u template arguments. As a best coding practice, the code example also uses rvalue
references and the forward function template, which support perfect forwarding. For more information, see
Rvalue Reference Declarator: &&.
//C++11
template<typename T, typename U>
auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u))
{ return forward<T>(t) + forward<U>(u); };
//C++14
template<typename T, typename U>
decltype(auto) myFunc(T&& t, U&& u)
{ return forward<T>(t) + forward<U>(u); };
Examples
The following code example declares the late-specified return type of template function Plus() . The Plus
function processes its two operands with the operator+ overload. Consequently, the interpretation of the plus
operator ( + ) and the return type of the Plus function depends on the types of the function arguments.
// decltype_1.cpp
// compile with: cl /EHsc decltype_1.cpp
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>
class X
{
friend X operator+(const X& x1, const X& x2)
{
return X(x1.m_data + x2.m_data);
}
public:
X(int data) : m_data(data) {}
int Dump() const { return m_data;}
private:
int m_data;
};
int main()
{
// Integer
int i = 4;
cout <<
"Plus(i, 9) = " <<
Plus(i, 9) << endl;
// Floating point
float dx = 4.0;
float dy = 9.5;
cout <<
setprecision(3) <<
"Plus(dx, dy) = " <<
Plus(dx, dy) << endl;
// String
string hello = "Hello, ";
string world = "world!";
cout << Plus(hello, world) << endl;
// Custom type
X x1(20);
X x2(22);
X x3 = Plus(x1, x2);
cout <<
"x3.Dump() = " <<
x3.Dump() << endl;
}
Plus(i, 9) = 13
Plus(dx, dy) = 13.5
Hello, world!
x3.Dump() = 42
Visual Studio 2017 and later : The compiler parses decltype arguments when the templates are declared
rather than instantiated. Consequently, if a non-dependent specialization is found in the decltype argument, it
will not be deferred to instantiation-time and will be processed immediately and any resulting errors will be
diagnosed at that time.
The following example shows such a compiler error that is raised at the point of declaration:
#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
{
public:
struct BadType {};
template <class U>
static decltype(std::declval<T>()(std::declval<ArgsT>()...)) Test(int); //C2064. Should be declval<U>
template <class U>
static BadType Test(...);
static constexpr bool value = std::is_convertible<decltype(Test<T>(0)), ReturnT>::value;
};
Requirements
Visual Studio 2010 or later versions.
decltype(auto) requires Visual Studio 2015 or later.
Attributes in C++
4/19/2021 • 4 minutes to read • Edit Online
The C++ Standard defines a common set of attributes. It also allows compiler vendors to define their own
attributes within a vendor-specific namespace. However, compilers are only required to recognize the attributes
defined in the standard.
In some cases, standard attributes overlap with compiler-specific __declspec parameters. In Microsoft C++, you
can use the [[deprecated]] attribute instead of using __declspec(deprecated) . The [[deprecated]] attribute is
recognized by any conforming compiler. For all other __declspec parameters such as dllimport and
dllexport , so far there's no attribute equivalent, so you must continue to use __declspec syntax. Attributes
don't affect the type system, and they don’t change the meaning of a program. Compilers ignore attribute values
they don't recognize.
Visual Studio 2017 version 15.3 and later (available with /std:c++17 ): In the scope of an attribute list, you
can specify the namespace for all names with a single using introducer:
void g() {
[[using rpr: kernel, target(cpu,gpu)]] // equivalent to [[ rpr::kernel, rpr::target(cpu,gpu) ]]
do task();
}
[[deprecated]]
void Foo(int);
[[nodiscard]]
int foo(int i) { return i * i; }
int main()
{
foo(42); //warning C4834: discarding return value of function with 'nodiscard' attribute
return 0;
}
[[maybe_unused]] Visual Studio 2017 version 15.3 and later : (available with /std:c++17 ) Specifies
that a variable, function, class, typedef, non-static data member, enum, or template specialization may
intentionally not be used. The compiler doesn't warn when an entity marked [[maybe_unused]] isn't used.
An entity that's declared without the attribute can later be redeclared with the attribute and vice-versa. An
entity is considered marked after its first declaration that's marked [[maybe_unused]] gets analyzed, and
for the rest of the current translation unit.
Microsoft-specific attributes
[[gsl::suppress(rules)]] This Microsoft-specific attribute is used for suppressing warnings from
checkers that enforce Guidelines Support Library (GSL) rules in code. For example, consider this code
snippet:
int main()
{
int arr[10]; // GSL warning C26494 will be fired
int* p = arr; // GSL warning C26485 will be fired
[[gsl::suppress(bounds.1)]] // This attribute suppresses Bounds rule #1
{
int* q = p + 1; // GSL warning C26481 suppressed
p = q--; // GSL warning C26481 suppressed
}
}
The C++ language includes all C operators and adds several new operators. Operators specify an evaluation to
be performed on one or more operands.
Alternative spellings
C++ specifies alternative spellings for some operators. In C, the alternative spellings are provided as macros in
the <iso646.h> header. In C++, these alternatives are keywords, and use of <iso646.h> or the C++ equivalent
<ciso646> is deprecated. In Microsoft C++, the /permissive- or /Za compiler option is required to enable the
alternative spellings.
Group 1 precedence, no
associativity
Scope resolution ::
Array subscript []
Function call ()
Postfix increment ++
Postfix decrement --
Prefix increment ++
Prefix decrement --
Unary negation -
Unary plus +
Address-of &
Indirection *
Cast ()
Multiplication *
Division /
Modulus %
O P ERATO R DESC RIP T IO N O P ERATO R A LT ERN AT IVE
Addition +
Subtraction -
Equality ==
Inequality != not_eq
Logical OR || or
Conditional ? :
Assignment =
Multiplication assignment *=
Division assignment /=
Modulus assignment %=
Addition assignment +=
Subtraction assignment -=
Comma ,
See also
Operator overloading
alignof Operator
3/6/2021 • 2 minutes to read • Edit Online
The alignof operator returns the alignment in bytes of the specified type as a value of type size_t .
Syntax
alignof( type )
Remarks
For example:
EXP RESSIO N VA L UE
alignof( char ) 1
alignof( short ) 2
alignof( int ) 4
alignof( float ) 4
alignof( double ) 8
The alignof value is the same as the value for sizeof for basic types. Consider, however, this example:
In this case, the alignof value is the alignment requirement of the largest element in the structure.
Similarly, for
alignof(S) is equal to 32 .
One use for alignof would be as a parameter to one of your own memory-allocation routines. For example,
given the following defined structure S , you could call a memory-allocation routine named aligned_malloc to
allocate memory on a particular alignment boundary.
See also
Expressions with Unary Operators
Keywords
__uuidof Operator
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Retrieves the GUID attached to the expression.
Syntax
__uuidof ( expression )
Remarks
The expression can be a type name, pointer, reference, or array of that type, a template specialized on these
types, or a variable of these types. The argument is valid as long as the compiler can use it to find the attached
GUID.
A special case of this intrinsic is when either 0 or NULL is supplied as the argument. In this case, __uuidof will
return a GUID made up of zeros.
Use this keyword to extract the GUID attached to:
An object by the uuid extended attribute.
A library block created with the module attribute.
NOTE
In a debug build, __uuidof always initializes an object dynamically (at runtime). In a release build, __uuidof can
statically (at compile time) initialize an object.
For compatibility with previous versions, _uuidof is a synonym for __uuidof unless compiler option /Za
(Disable language extensions) is specified.
Example
The following code (compiled with ole32.lib) will display the uuid of a library block created with the module
attribute:
// expre_uuidof.cpp
// compile with: ole32.lib
#include "stdio.h"
#include "windows.h"
[emitidl];
[module(name="MyLib")];
[export]
struct stuff {
int i;
};
int main() {
LPOLESTR lpolestr;
StringFromCLSID(__uuidof(MyLib), &lpolestr);
wprintf_s(L"%s", lpolestr);
CoTaskMemFree(lpolestr);
}
Comments
In cases where the library name is no longer in scope, you can use __LIBID_ instead of __uuidof . For example:
StringFromCLSID(__LIBID_, &lpolestr);
See also
Expressions with Unary Operators
Keywords
Additive Operators: + and -
3/6/2021 • 2 minutes to read • Edit Online
Syntax
expression + expression
expression - expression
Remarks
The additive operators are:
Addition (+ )
Subtraction (- )
These binary operators have left-to-right associativity.
The additive operators take operands of arithmetic or pointer types. The result of the addition (+ ) operator is the
sum of the operands. The result of the subtraction (- ) operator is the difference between the operands. If one or
both of the operands are pointers, they must be pointers to objects, not to functions. If both operands are
pointers, the results are not meaningful unless both are pointers to objects in the same array.
Additive operators take operands of arithmetic, integral, and scalar types. These are defined in the following
table.
Types Used with Additive Operators
TYPE M EA N IN G
integral Types char and int of all sizes (long, short) and enumerations
are "integral" types.
Example
// expre_Additive_Operators.cpp
// compile with: /EHsc
#include <iostream>
#define SIZE 5
using namespace std;
int main() {
int i = 5, j = 10;
int n[SIZE] = { 0, 1, 2, 3, 4 };
cout << "5 + 10 = " << i + j << endl
<< "5 - 10 = " << i - j << endl;
Pointer addition
If one of the operands in an addition operation is a pointer to an array of objects, the other must be of integral
type. The result is a pointer that is of the same type as the original pointer and that points to another array
element. The following code fragment illustrates this concept:
Although the integral value 1 is added to pIntArray , it does not mean "add 1 to the address"; rather it means
"adjust the pointer to point to the next object in the array" that happens to be 2 bytes (or sizeof( int ) ) away.
NOTE
Code of the form pIntArray = pIntArray + 1 is rarely found in C++ programs; to perform an increment, these forms
are preferable: pIntArray++ or pIntArray += 1 .
Pointer subtraction
If both operands are pointers, the result of subtraction is the difference (in array elements) between the
operands. The subtraction expression yields a signed integral result of type ptrdiff_t (defined in the standard
include file <stddef.h>).
One of the operands can be of integral type, as long as it is the second operand. The result of the subtraction is
of the same type as the original pointer. The value of the subtraction is a pointer to the (n - i)th array element,
where n is the element pointed to by the original pointer and i is the integral value of the second operand.
See also
Expressions with Binary Operators
C++ Built-in Operators, Precedence and Associativity
C Additive Operators
Address-of Operator: &
11/2/2020 • 2 minutes to read • Edit Online
Syntax
& cast-expression
Remarks
The unary address-of operator ( & ) takes the address of its operand. The operand of the address-of operator
can be either a function designator or an l-value that designates an object that's not a bit field.
The address-of operator can only be applied to variables of fundamental, structure, class, or union types that are
declared at the file-scope level, or to subscripted array references. In these expressions, a constant expression
that doesn't include the address-of operator can be added to or subtracted from the address-of expression.
When applied to functions or l-values, the result of the expression is a pointer type (an r-value) derived from the
type of the operand. For example, if the operand is of type char , the result of the expression is of type pointer
to char . The address-of operator, applied to const or volatile objects, evaluates to const type * or
volatile type * , where type is the type of the original object.
The address of an overloaded function can be taken only when it's clear which version of the function is being
referenced. See Function Overloading for information about how to obtain the address of a particular
overloaded function.
When the address-of operator is applied to a qualified name, the result depends on whether the qualified-name
specifies a static member. If so, the result is a pointer to the type specified in the declaration of the member. For a
member that isn't static, the result is a pointer to the member name of the class indicated by qualified-class-
name. For more information about qualified-class-name, see Primary expressions.
// expre_Address_Of_Operator.cpp
// C2440 expected
class PTM {
public:
int iValue;
static float fValue;
};
int main() {
int PTM::*piValue = &PTM::iValue; // OK: non-static
float PTM::*pfValue = &PTM::fValue; // C2440 error: static
float *spfValue = &PTM::fValue; // OK
}
In this example, the expression &PTM::fValue yields type float * instead of type float PTM::* because
fValue is a static member.
Example: Address of a reference type
Applying the address-of operator to a reference type gives the same result as applying the operator to the
object to which the reference is bound. For example:
// expre_Address_Of_Operator2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main() {
double d; // Define an object of type double.
double& rd = d; // Define a reference to the object.
// expre_Address_Of_Operator3.cpp
// compile with: /EHsc
// Demonstrate address-of operator &
#include <iostream>
using namespace std;
int main() {
int mynum = 5;
cout << square( &mynum ) << endl; // pass address of int
}
25
See also
Expressions with Unary Operators
C++ Built-in Operators, Precedence, and Associativity
Lvalue Reference Declarator: &
Indirection and Address-of Operators
Assignment operators
11/2/2020 • 5 minutes to read • Edit Online
Syntax
expression assignment-operator expression
assignment-operator: one of
= *= /= %= += -= <<= >>= &= ^= |=
Remarks
Assignment operators store a value in the object specified by the left operand. There are two kinds of
assignment operations:
simple assignment, in which the value of the second operand is stored in the object specified by the first
operand.
compound assignment, in which an arithmetic, shift, or bitwise operation is performed before storing the
result.
All assignment operators in the following table except the = operator are compound assignment operators.
Assignment operators table
O P ERATO R M EA N IN G
+= Add the value of the second operand to the value of the first
operand; store the result in the object specified by the first
operand.
<<= Shift the value of the first operand left the number of bits
specified by the value of the second operand; store the
result in the object specified by the first operand.
O P ERATO R M EA N IN G
>>= Shift the value of the first operand right the number of bits
specified by the value of the second operand; store the
result in the object specified by the first operand.
&= Obtain the bitwise AND of the first and second operands;
store the result in the object specified by the first operand.
Operator keywords
Three of the compound assignment operators have keyword equivalents. They are:
O P ERATO R EQ UIVA L EN T
&= and_eq
|= or_eq
^= xor_eq
C++ specifies these operator keywords as alternative spellings for the compound assignment operators. In C,
the alternative spellings are provided as macros in the <iso646.h> header. In C++, the alternative spellings are
keywords; use of <iso646.h> or the C++ equivalent <ciso646> is deprecated. In Microsoft C++, the
/permissive- or /Za compiler option is required to enable the alternative spelling.
Example
// expre_Assignment_Operators.cpp
// compile with: /EHsc
// Demonstrate assignment operators
#include <iostream>
using namespace std;
int main() {
int a = 3, b = 6, c = 10, d = 0xAAAA, e = 0x5555;
a += b; // a is 9
b %= a; // b is 6
c >>= 1; // c is 5
d |= e; // Bitwise--d is 0xFFFF
Simple assignment
The simple assignment operator ( = ) causes the value of the second operand to be stored in the object specified
by the first operand. If both objects are of arithmetic types, the right operand is converted to the type of the left,
before storing the value.
Objects of const and volatile types can be assigned to l-values of types that are only volatile , or that aren't
const or volatile .
Assignment to objects of class type ( struct , union , and class types) is performed by a function named
operator= . The default behavior of this operator function is to perform a bitwise copy; however, this behavior
can be modified using overloaded operators. For more information, see Operator overloading. Class types can
also have copy assignment and move assignment operators. For more information, see Copy constructors and
copy assignment operators and Move constructors and move assignment operators.
An object of any unambiguously derived class from a given base class can be assigned to an object of the base
class. The reverse isn't true because there's an implicit conversion from derived class to base class, but not from
base class to derived class. For example:
// expre_SimpleAssignment.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class ABase
{
public:
ABase() { cout << "constructing ABase\n"; }
};
int main()
{
ABase aBase;
ADerived aDerived;
aBase = aDerived; // OK
aDerived = aBase; // C2679
}
Assignments to reference types behave as if the assignment were being made to the object to which the
reference points.
For class-type objects, assignment is different from initialization. To illustrate how different assignment and
initialization can be, consider the code
UserType1 A;
UserType2 B = A;
The preceding code shows an initializer; it calls the constructor for UserType2 that takes an argument of type
UserType1 . Given the code
UserType1 A;
UserType2 B;
B = A;
the assignment statement
B = A;
Compound assignment
The compound assignment operators are shown in the Assignment operators table. These operators have the
form e1 op= e2, where e1 is a non- const modifiable l-value and e2 is:
an arithmetic type
a pointer, if op is + or -
See also
Expressions with binary operators
C++ built-in operators, precedence, and associativity
C assignment operators
Bitwise AND operator: &
11/2/2020 • 2 minutes to read • Edit Online
Syntax
expression & expression
Remarks
The bitwise AND operator ( & ) compares each bit of the first operand to the corresponding bit of the second
operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set
to 0.
Both operands to the bitwise AND operator must have integral types. The usual arithmetic conversions covered
in Standard Conversions are applied to the operands.
Example
// expre_Bitwise_AND_Operator.cpp
// compile with: /EHsc
// Demonstrate bitwise AND
#include <iostream>
using namespace std;
int main() {
unsigned short a = 0xFFFF; // pattern 1111 ...
unsigned short b = 0xAAAA; // pattern 1010 ...
cout << hex << ( a & b ) << endl; // prints "aaaa", pattern 1010 ...
}
See also
C++ built-in operators, precedence, and associativity
C bitwise operators
Bitwise exclusive OR operator: ^
11/2/2020 • 2 minutes to read • Edit Online
Syntax
expression ^ expression
Remarks
The bitwise exclusive OR operator ( ^ ) compares each bit of its first operand to the corresponding bit of its
second operand. If the bit in one of the operands is 0 and the bit in the other operand is 1, the corresponding
result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
Both operands to the operator must have integral types. The usual arithmetic conversions covered in Standard
Conversions are applied to the operands.
For more information on the alternate usage of the ^ character in C++/CLI and C++/CX, see Handle to Object
Operator (^) (C++/CLI and C++/CX).
Example
// expre_Bitwise_Exclusive_OR_Operator.cpp
// compile with: /EHsc
// Demonstrate bitwise exclusive OR
#include <iostream>
using namespace std;
int main() {
unsigned short a = 0x5555; // pattern 0101 ...
unsigned short b = 0xFFFF; // pattern 1111 ...
cout << hex << ( a ^ b ) << endl; // prints "aaaa" pattern 1010 ...
}
See also
C++ built-in operators, precedence, and associativity
Bitwise inclusive OR operator: |
11/2/2020 • 2 minutes to read • Edit Online
Syntax
expression1 | expression2
Remarks
The bitwise inclusive OR operator ( | ) compares each bit of its first operand to the corresponding bit of its
second operand. If either bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit
is set to 0.
Both operands to the operator must have integral types. The usual arithmetic conversions covered in Standard
Conversions are applied to the operands.
Example
// expre_Bitwise_Inclusive_OR_Operator.cpp
// compile with: /EHsc
// Demonstrate bitwise inclusive OR
#include <iostream>
using namespace std;
int main() {
unsigned short a = 0x5555; // pattern 0101 ...
unsigned short b = 0xAAAA; // pattern 1010 ...
cout << hex << ( a | b ) << endl; // prints "ffff" pattern 1111 ...
}
See also
C++ built-in operators, precedence, and associativity
C bitwise operators
Cast Operator: ()
3/6/2021 • 2 minutes to read • Edit Online
A type cast provides a method for explicit conversion of the type of an object in a specific situation.
Syntax
unary-expression ( type-name ) cast-expression
Remarks
Any unary expression is considered a cast expression.
The compiler treats cast-expression as type type-name after a type cast has been made. Casts can be used to
convert objects of any scalar type to or from any other scalar type. Explicit type casts are constrained by the
same rules that determine the effects of implicit conversions. Additional restraints on casts may result from the
actual sizes or representation of specific types.
Examples
// expre_CastOperator.cpp
// compile with: /EHsc
// Demonstrate cast operator
#include <iostream>
int main()
{
double x = 3.1;
int i;
cout << "x = " << x << endl;
i = (int)x; // assign i the integer part of x
cout << "i = " << i << endl;
}
// expre_CastOperator2.cpp
// The following sample shows how to define and use a cast operator.
#include <string.h>
#include <stdio.h>
class CountedAnsiString
{
public:
// Assume source is not null terminated
CountedAnsiString(const char *pStr, size_t nSize) :
m_nSize(nSize)
{
m_pStr = new char[sizeOfBuffer];
//
// operator to cast to a const char *
//
operator const char *()
{
m_pStr[m_nSize] = '\0';
return(m_pStr);
}
enum
{
sizeOfBuffer = 20
} size;
private:
char *m_pStr;
const size_t m_nSize;
};
int main()
{
const char *kStr = "Excitinggg";
CountedAnsiString myStr(kStr, 8);
Syntax
expression , expression
Remarks
The comma operator has left-to-right associativity. Two expressions separated by a comma are evaluated left to
right. The left operand is always evaluated, and all side effects are completed before the right operand is
evaluated.
Commas can be used as separators in some contexts, such as function argument lists. Do not confuse the use of
the comma as a separator with its use as an operator; the two uses are completely different.
Consider the expression e1, e2 . The type and value of the expression are the type and value of e2; the result of
evaluating e1 is discarded. The result is an l-value if the right operand is an l-value.
Where the comma is normally used as a separator (for example in actual arguments to functions or aggregate
initializers), the comma operator and its operands must be enclosed in parentheses. For example:
func_one( x, y + 2, z );
func_two( (x--, y + 2), z );
In the function call to func_one above, three arguments, separated by commas, are passed: x , y + 2 , and z .
In the function call to func_two , parentheses force the compiler to interpret the first comma as the sequential-
evaluation operator. This function call passes two arguments to func_two . The first argument is the result of the
sequential-evaluation operation (x--, y + 2) , which has the value and type of the expression y + 2 ; the
second argument is z .
Example
// cpp_comma_operator.cpp
#include <stdio.h>
int main () {
int i = 10, b = 20, c= 30;
i = b, c;
printf("%i\n", i);
i = (b, c);
printf("%i\n", i);
}
20
30
See also
Expressions with Binary Operators
C++ Built-in Operators, Precedence and Associativity
Sequential-Evaluation Operator
Conditional Operator: ? :
3/6/2021 • 2 minutes to read • Edit Online
Syntax
expression ? expression : expression
Remarks
The conditional operator (? :) is a ternary operator (it takes three operands). The conditional operator works as
follows:
The first operand is implicitly converted to bool . It is evaluated and all side effects are completed before
continuing.
If the first operand evaluates to true (1), the second operand is evaluated.
If the first operand evaluates to false (0), the third operand is evaluated.
The result of the conditional operator is the result of whichever operand is evaluated — the second or the third.
Only one of the last two operands is evaluated in a conditional expression.
Conditional expressions have right-to-left associativity. The first operand must be of integral or pointer type. The
following rules apply to the second and third operands:
If both operands are of the same type, the result is of that type.
If both operands are of arithmetic or enumeration types, the usual arithmetic conversions (covered in
Standard Conversions) are performed to convert them to a common type.
If both operands are of pointer types or if one is a pointer type and the other is a constant expression that
evaluates to 0, pointer conversions are performed to convert them to a common type.
If both operands are of reference types, reference conversions are performed to convert them to a
common type.
If both operands are of type void, the common type is type void.
If both operands are of the same user-defined type, the common type is that type.
If the operands have different types and at least one of the operands has user-defined type then the
language rules are used to determine the common type. (See warning below.)
Any combinations of second and third operands not in the preceding list are illegal. The type of the result is the
common type, and it is an l-value if both the second and third operands are of the same type and both are l-
values.
WARNING
If the types of the second and third operands are not identical, then complex type conversion rules, as specified in the
C++ Standard, are invoked. These conversions may lead to unexpected behavior including construction and destruction of
temporary objects. For this reason, we strongly advise you to either (1) avoid using user-defined types as operands with
the conditional operator or (2) if you do use user-defined types, then explicitly cast each operand to a common type.
Example
// expre_Expressions_with_the_Conditional_Operator.cpp
// compile with: /EHsc
// Demonstrate conditional operator
#include <iostream>
using namespace std;
int main() {
int i = 1, j = 2;
cout << ( i > j ? i : j ) << " is greater." << endl;
}
See also
C++ Built-in Operators, Precedence and Associativity
Conditional-Expression Operator
delete Operator (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
[ :: ] delete cast-expression
[ :: ] delete [] cast-expression
Remarks
The cast-expression argument must be a pointer to a block of memory previously allocated for an object created
with the new operator. The delete operator has a result of type void and therefore does not return a value.
For example:
Using delete on a pointer to an object not allocated with new gives unpredictable results. You can, however,
use delete on a pointer with the value 0. This provision means that, when new returns 0 on failure, deleting
the result of a failed new operation is harmless. For more information, see The new and delete Operators.
The new and delete operators can also be used for built-in types, including arrays. If pointer refers to an
array, place empty brackets ( [] ) before pointer :
Using the delete operator on an object deallocates its memory. A program that dereferences a pointer after the
object is deleted can have unpredictable results or crash.
When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the
object's memory is deallocated (if the object has a destructor).
If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.
If the /sdl (Enable additional security checks) compiler option is specified, the operand to the delete operator is
set to an invalid value after the object is deleted.
Using delete
There are two syntactic variants for the delete operator: one for single objects and the other for arrays of objects.
The following code fragment shows how they differ:
// expre_Using_delete.cpp
struct UDType
{
};
int main()
{
// Allocate a user-defined object, UDObject, and an object
// of type double on the free store using the
// new operator.
UDType *UDObject = new UDType;
double *dObject = new double;
// Delete the two objects.
delete UDObject;
delete dObject;
// Allocate an array of user-defined objects on the
// free store using the new operator.
UDType (*UDArr)[7] = new UDType[5][7];
// Use the array syntax to delete the array of objects.
delete [] UDArr;
}
The following two cases produce undefined results: using the array form of delete ( delete [] ) on an object, and
using the nonarray form of delete on an array.
Example
For examples of using delete , see new operator.
See also
Expressions with Unary Operators
Keywords
new and delete Operators
Equality operators: == and !=
11/2/2020 • 2 minutes to read • Edit Online
Syntax
expression == expression
expression != expression
Remarks
The binary equality operators compare their operands for strict equality or inequality.
The equality operators, equal to ( == ) and not equal to ( != ), have lower precedence than the relational
operators, but they behave similarly. The result type for these operators is bool .
The equal-to operator ( == ) returns true if both operands have the same value; otherwise, it returns false .
The not-equal-to operator ( != ) returns true if the operands don't have the same value; otherwise, it returns
false .
Example
// expre_Equality_Operators.cpp
// compile with: /EHsc
#include <iostream>
int main() {
cout << boolalpha
<< "The true expression 3 != 2 yields: "
<< (3 != 2) << endl
<< "The false expression 20 == 10 yields: "
<< (20 == 10) << endl;
}
Equality operators can compare pointers to members of the same type. In such a comparison, pointer-to-
member conversions are performed. Pointers to members can also be compared to a constant expression that
evaluates to 0.
See also
Expressions with binary operators
C++ built-in operators, precedence; and associativity
C relational and equality operators
Explicit Type Conversion Operator: ()
3/6/2021 • 2 minutes to read • Edit Online
C++ allows explicit type conversion using syntax similar to the function-call syntax.
Syntax
simple-type-name ( expression-list )
Remarks
A simple-type-name followed by an expression-list enclosed in parentheses constructs an object of the specified
type using the specified expressions. The following example shows an explicit type conversion to type int:
int i = int( d );
Example
// expre_Explicit_Type_Conversion_Operator.cpp
// compile with: /EHsc
#include <iostream>
int main()
{
Point Point1, Point2;
Output
x = 20, y = 10
x = 0, y = 0
Although the preceding example demonstrates explicit type conversion using constants, the same technique
works to perform these conversions on objects. The following code fragment demonstrates this:
int i = 7;
float d;
d = float( i );
Explicit type conversions can also be specified using the "cast" syntax. The previous example, rewritten using the
cast syntax, is:
d = (float)i;
Both cast and function-style conversions have the same results when converting from single values. However, in
the function-style syntax, you can specify more than one argument for conversion. This difference is important
for user-defined types. Consider a Point class and its conversions:
struct Point
{
Point( short x, short y ) { _x = x; _y = y; }
...
short _x, _y;
};
...
Point pt = Point( 3, 10 );
The preceding example, which uses function-style conversion, shows how to convert two values (one for x and
one for y) to the user-defined type Point .
Cau t i on
Use the explicit type conversions with care, since they override the C++ compiler's built-in type checking.
The cast notation must be used for conversions to types that do not have a simple-type-name (pointer or
reference types, for example). Conversion to types that can be expressed with a simple-type-name can be
written in either form.
Type definition within casts is illegal.
See also
Postfix Expressions
C++ Built-in Operators, Precedence and Associativity
Function Call Operator: ()
3/6/2021 • 3 minutes to read • Edit Online
A function call is a kind of postfix-expression , formed by an expression that evaluates to a function or callable
object followed by the function-call operator, () . An object can declare an operator () function, which
provides function call semantics for the object.
Syntax
postfix-expression :
postfix-expression ( argument-expression-list opt )
Remarks
The arguments to the function-call operator come from an argument-expression-list , a comma-separated list of
expressions. The values of these expressions are passed to the function as arguments. The argument-expression-
list can be empty. Before C++ 17, the order of evaluation of the function expression and the argument
expressions is unspecified and may occur in any order. In C++17 and later, the function expression is evaluated
before any argument expressions or default arguments. The argument expressions are evaluated in an
indeterminate sequence.
The postfix-expression evaluates to the function to call. It can take any of several forms:
a function identifier, visible in the current scope or in the scope of any of the function arguments provided,
an expression that evaluates to a function, a function pointer, a callable object, or to a reference to one,
a member function accessor, either explicit or implied,
a dereferenced pointer to a member function.
The postfix-expression may be an overloaded function identifier or overloaded member function accessor. The
rules for overload resolution determine the actual function to call. If the member function is virtual, the function
to call is determined at run time.
Some example declarations:
Function returning type T . An example declaration is
T func( int i );
T (*func)( int i );
T (&func)(int i);
Example
The following example calls the standard library function strcat_s with three arguments:
// expre_Function_Call_Operator.cpp
// compile with: /EHsc
#include <iostream>
#include <string>
int main()
{
enum
{
sizeOfBuffer = 20
};
Welcome to C++
The preceding code defines a class called Point , which contains private data objects that represent x and y
coordinates. These data objects must be modified and their values retrieved. This program is only one of several
designs for such a class; use of the GetX and SetX or GetY and SetY functions is another possible design.
Functions that return class types, pointers to class types, or references to class types can be used as the left
operand to member-selection operators. The following code is legal:
// expre_Function_Results2.cpp
class A {
public:
A() {}
A(int i) {}
int SetA( int i ) {
return (I = i);
}
int GetA() {
return I;
}
private:
int I;
};
A func1() {
A a = 0;
return a;
}
A* func2() {
A *a = new A();
return a;
}
A& func3() {
A *a = new A();
A &b = *a;
return b;
}
int main() {
int iResult = func1().GetA();
func2()->SetA( 3 );
func3().SetA( 7 );
}
Functions can be called recursively. For more information about function declarations, see Functions. Related
material is in Translation units and linkage.
See also
Postfix expressions
C++ built-in operators, precedence, and associativity
Function call
Indirection Operator: *
3/6/2021 • 2 minutes to read • Edit Online
Syntax
* cast-expression
Remarks
The unary indirection operator (* ) dereferences a pointer; that is, it converts a pointer value to an l-value. The
operand of the indirection operator must be a pointer to a type. The result of the indirection expression is the
type from which the pointer type is derived. The use of the * operator in this context is different from its
meaning as a binary operator, which is multiplication.
If the operand points to a function, the result is a function designator. If it points to a storage location, the result
is an l-value designating the storage location.
The indirection operator may be used cumulatively to dereference pointers to pointers. For example:
// expre_Indirection_Operator.cpp
// compile with: /EHsc
// Demonstrate indirection operator
#include <iostream>
using namespace std;
int main() {
int n = 5;
int *pn = &n;
int **ppn = &pn;
If the pointer value is invalid, the result is undefined. The following list includes some of the most common
conditions that invalidate a pointer value.
The pointer is a null pointer.
The pointer specifies the address of a local item that is not visible at the time of the reference.
The pointer specifies an address that is inappropriately aligned for the type of the object pointed to.
The pointer specifies an address not used by the executing program.
See also
Expressions with Unary Operators
C++ Built-in Operators, Precedence and Associativity
Address-of Operator: &
Indirection and Address-of Operators
Left Shift and Right Shift Operators (>> and <<)
3/6/2021 • 5 minutes to read • Edit Online
The bitwise shift operators are the right-shift operator (>> ), which moves the bits of shift-expression to the
right, and the left-shift operator (<< ), which moves the bits of shift-expression to the left. 1
Syntax
shift-expression << additive-expression
shift-expression >> additive-expression
Remarks
IMPORTANT
The following descriptions and examples are valid on Windows for x86 and x64 architectures. The implementation of left-
shift and right-shift operators is significantly different on Windows for ARM devices. For more information, see the "Shift
Operators" section of the Hello ARM blog post.
Left Shifts
The left-shift operator causes the bits in shift-expression to be shifted to the left by the number of positions
specified by additive-expression. The bit positions that have been vacated by the shift operation are zero-filled. A
left shift is a logical shift (the bits that are shifted off the end are discarded, including the sign bit). For more
information about the kinds of bitwise shifts, see Bitwise shifts.
The following example shows left-shift operations using unsigned numbers. The example shows what is
happening to the bits by representing the value as a bitset. For more information, see bitset Class.
#include <iostream>
#include <bitset>
int main() {
unsigned short short1 = 4;
bitset<16> bitset1{short1}; // the bitset representation of 4
cout << bitset1 << endl; // 0b00000000'00000100
If you left-shift a signed number so that the sign bit is affected, the result is undefined. The following example
shows what happens when a 1 bit is left-shifted into the sign bit position.
#include <iostream>
#include <bitset>
int main() {
short short1 = 16384;
bitset<16> bitset1(short1);
cout << bitset1 << endl; // 0b01000000'00000000
Right Shifts
The right-shift operator causes the bit pattern in shift-expression to be shifted to the right by the number of
positions specified by additive-expression. For unsigned numbers, the bit positions that have been vacated by
the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In
other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.
IMPORTANT
The result of a right-shift of a signed negative number is implementation-dependent. Although the Microsoft C++
compiler uses the sign bit to fill vacated bit positions, there is no guarantee that other implementations also do so.
#include <iostream>
#include <bitset>
int main() {
unsigned short short11 = 1024;
bitset<16> bitset11{short11};
cout << bitset11 << endl; // 0b00000100'00000000
The next example shows right-shift operations with positive signed numbers.
#include <iostream>
#include <bitset>
int main() {
short short1 = 1024;
bitset<16> bitset1(short1);
cout << bitset1 << endl; // 0b00000100'00000000
The next example shows right-shift operations with negative signed integers.
#include <iostream>
#include <bitset>
int main() {
short neg1 = -16;
bitset<16> bn1(neg1);
cout << bn1 << endl; // 0b11111111'11110000
int main() {
char char1 = 'a';
Additional Details
The result of a shift operation is undefined if additive-expression is negative or if additive-expression is greater
than or equal to the number of bits in the (promoted) shift-expression. No shift operation is performed if
additive-expression is 0.
#include <iostream>
#include <bitset>
int main() {
unsigned int int1 = 4;
bitset<32> b1{int1};
cout << b1 << endl; // 0b00000000'00000000'00000000'00000100
unsigned int int2 = int1 << -3; // C4293: '<<' : shift count negative or too big, undefined behavior
unsigned int int3 = int1 >> -3; // C4293: '>>' : shift count negative or too big, undefined behavior
unsigned int int4 = int1 << 32; // C4293: '<<' : shift count negative or too big, undefined behavior
unsigned int int5 = int1 >> 32; // C4293: '>>' : shift count negative or too big, undefined behavior
unsigned int int6 = int1 << 0;
bitset<32> b6{int6};
cout << b6 << endl; // 0b00000000'00000000'00000000'00000100 (no change)
}
Footnotes
1 The following is the description of the shift operators in the C++11 ISO specification (INCITS/ISO/IEC 14882-
2011[2012]), sections 5.8.2 and 5.8.3.
The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned
type, the value of the result is E1 × 2 E2 , reduced modulo one more than the maximum value representable in
the result type. Otherwise, if E1 has a signed type and non-negative value, and E1 × 2 E2 is representable in the
corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting
value; otherwise, the behavior is undefined.
The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed
type and a non-negative value, the value of the result is the integral part of the quotient of E1/2 E2 . If E1 has a
signed type and a negative value, the resulting value is implementation-defined.
See also
Expressions with Binary Operators
C++ Built-in Operators, Precedence and Associativity
Logical AND operator: &&
11/2/2020 • 2 minutes to read • Edit Online
Syntax
expression && expression
Remarks
The logical AND operator (&& ) returns true if both operands are true and returns false otherwise. The
operands are implicitly converted to type bool before evaluation, and the result is of type bool . Logical AND
has left-to-right associativity.
The operands to the logical AND operator don't need to have the same type, but they must have boolean,
integral, or pointer type. The operands are commonly relational or equality expressions.
The first operand is completely evaluated and all side effects are completed before evaluation of the logical AND
expression continues.
The second operand is evaluated only if the first operand evaluates to true (nonzero). This evaluation
eliminates needless evaluation of the second operand when the logical AND expression is false . You can use
this short-circuit evaluation to prevent null-pointer dereferencing, as shown in the following example:
char *pch = 0;
// ...
(pch) && (*pch = 'a');
If pch is null (0), the right side of the expression is never evaluated. This short-circuit evaluation makes the
assignment through a null pointer impossible.
Example
// expre_Logical_AND_Operator.cpp
// compile with: /EHsc
// Demonstrate logical AND
#include <iostream>
int main() {
int a = 5, b = 10, c = 15;
cout << boolalpha
<< "The true expression "
<< "a < b && b < c yields "
<< (a < b && b < c) << endl
<< "The false expression "
<< "a > b && b < c yields "
<< (a > b && b < c) << endl;
}
See also
C++ built-in operators, precedence, and associativity
C logical operators
Logical negation operator: !
11/2/2020 • 2 minutes to read • Edit Online
Syntax
! cast-expression
Remarks
The logical negation operator ( ! ) reverses the meaning of its operand. The operand must be of arithmetic or
pointer type (or an expression that evaluates to arithmetic or pointer type). The operand is implicitly converted
to type bool . The result is true if the converted operand is false ; the result is false if the converted
operand is true . The result is of type bool .
For an expression e , the unary expression !e is equivalent to the expression (e == 0) , except where
overloaded operators are involved.
Example
// expre_Logical_NOT_Operator.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main() {
int i = 0;
if (!i)
cout << "i is zero" << endl;
}
See also
Expressions with unary operators
C++ built-in operators, precedence, and associativity
Unary arithmetic operators
Logical OR operator: ||
11/2/2020 • 2 minutes to read • Edit Online
Syntax
logical-or-expression || logical-and-expression
Remarks
The logical OR operator ( || ) returns the boolean value true if either or both operands is true and returns
false otherwise. The operands are implicitly converted to type bool before evaluation, and the result is of
type bool . Logical OR has left-to-right associativity.
The operands to the logical OR operator don't have to have the same type, but they must be of boolean, integral,
or pointer type. The operands are commonly relational or equality expressions.
The first operand is completely evaluated and all side effects are completed before continuing evaluation of the
logical OR expression.
The second operand is evaluated only if the first operand evaluates to false , because evaluation isn't needed
when the logical OR expression is true . It's known as short-circuit evaluation.
printf( "%d" , (x == w || x == y || x == z) );
In the above example, if x is equal to either w , y , or z , the second argument to the printf function
evaluates to true , which is then promoted to an integer, and the value 1 is printed. Otherwise, it evaluates to
false and the value 0 is printed. As soon as one of the conditions evaluates to true , evaluation stops.
Example
// expre_Logical_OR_Operator.cpp
// compile with: /EHsc
// Demonstrate logical OR
#include <iostream>
using namespace std;
int main() {
int a = 5, b = 10, c = 15;
cout << boolalpha
<< "The true expression "
<< "a < b || b > c yields "
<< (a < b || b > c) << endl
<< "The false expression "
<< "a > b || b > c yields "
<< (a > b || b > c) << endl;
}
See also
C++ built-in operators, precedence, and associativity
C logical operators
Member Access Operators: . and ->
3/6/2021 • 2 minutes to read • Edit Online
Syntax
postfix-expression . name
postfix-expression -> name
Remarks
The member access operators . and -> are used to refer to members of structures, unions, and classes. Member
access expressions have the value and type of the selected member.
There are two forms of member access expressions:
1. In the first form, postfix-expression represents a value of struct, class, or union type, and name names a
member of the specified structure, union, or class. The value of the operation is that of name and is an l-
value if postfix-expression is an l-value.
2. In the second form, postfix-expression represents a pointer to a structure, union, or class, and name
names a member of the specified structure, union, or class. The value is that of name and is an l-value.
The -> operator dereferences the pointer. Therefore, the expressions e->member and (*e).member (where
e represents a pointer) yield identical results (except when the operators -> or * are overloaded).
Example
The following example demonstrates both forms of the member access operator.
// expre_Selection_Operator.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct Date {
Date(int i, int j, int k) : day(i), month(j), year(k){}
int month;
int day;
int year;
};
int main() {
Date mydate(1,1,1900);
mydate.month = 2;
cout << mydate.month << "/" << mydate.day
<< "/" << mydate.year << endl;
See also
Postfix Expressions
C++ Built-in Operators, Precedence and Associativity
Classes and Structs
Structure and Union Members
Multiplicative Operators and the Modulus Operator
3/6/2021 • 2 minutes to read • Edit Online
Syntax
expression * expression
expression / expression
expression % expression
Remarks
The multiplicative operators are:
Multiplication (* )
Division (/ )
Modulus (remainder from division) (% )
These binary operators have left-to-right associativity.
The multiplicative operators take operands of arithmetic types. The modulus operator (% ) has a stricter
requirement in that its operands must be of integral type. (To get the remainder of a floating-point division, use
the run-time function, fmod.) The conversions covered in Standard Conversions are applied to the operands, and
the result is of the converted type.
The multiplication operator yields the result of multiplying the first operand by the second.
The division operator yields the result of dividing the first operand by the second.
The modulus operator yields the remainder given by the following expression, where e1 is the first operand and
e2 is the second: e1 - (e1 / e2) * e2, where both operands are of integral types.
Division by 0 in either a division or a modulus expression is undefined and causes a run-time error. Therefore,
the following expressions generate undefined, erroneous results:
i % 0
f / 0.0
If both operands to a multiplication, division, or modulus expression have the same sign, the result is positive.
Otherwise, the result is negative. The result of a modulus operation's sign is implementation-defined.
NOTE
Since the conversions performed by the multiplicative operators do not provide for overflow or underflow conditions,
information may be lost if the result of a multiplicative operation cannot be represented in the type of the operands after
conversion.
Microsoft Specific
In Microsoft C++, the result of a modulus expression is always the same as the sign of the first operand.
END Microsoft Specific
If the computed division of two integers is inexact and only one operand is negative, the result is the largest
integer (in magnitude, disregarding the sign) that is less than the exact value the division operation would yield.
For example, the computed value of -11 / 3 is -3.666666666. The result of that integral division is -3.
The relationship between the multiplicative operators is given by the identity (e1 / e2) * e2 + e1 % e2 == e1.
Example
The following program demonstrates the multiplicative operators. Note that either operand of 10 / 3 must be
explicitly cast to type float to avoid truncation so that both operands are of type float before division.
// expre_Multiplicative_Operators.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main() {
int x = 3, y = 6, z = 10;
cout << "3 * 6 is " << x * y << endl
<< "6 / 3 is " << y / x << endl
<< "10 % 3 is " << z % x << endl
<< "10 / 3 is " << (float) z / x << endl;
}
See also
Expressions with Binary Operators
C++ Built-in Operators, Precedence and Associativity
C Multiplicative Operators
new Operator (C++)
3/6/2021 • 8 minutes to read • Edit Online
Allocates memory for an object or array of objects of type-name from the free store and returns a suitably
typed, nonzero pointer to the object.
NOTE
Microsoft C++ Component Extensions provides support for the new keyword to add vtable slot entries. For more
information, see new (new slot in vtable)
Syntax
[::] new [placement] new-type-name [new-initializer]
[::] new [placement] ( type-name ) [new-initializer]
Remarks
If unsuccessful, new returns zero or throws an exception; see The new and delete Operators for more
information. You can change this default behavior by writing a custom exception-handling routine and calling
the _set_new_handler run-time library function with your function name as its argument.
For information on how to create an object on the managed heap, see gcnew.
When new is used to allocate memory for a C++ class object, the object's constructor is called after the
memory is allocated.
Use the delete operator to deallocate the memory allocated with the new operator.
The following example allocates and then frees a two-dimensional array of characters of size dim by 10. When
allocating a multidimensional array, all dimensions except the first must be constant expressions that evaluate to
positive values; the leftmost array dimension can be any expression that evaluates to a positive value. When
allocating an array using the new operator, the first dimension can be zero — the new operator returns a
unique pointer.
The type-name cannot contain const , volatile , class declarations, or enumeration declarations. Therefore, the
following expression is illegal:
The new operator does not allocate reference types because they are not objects.
The new operator cannot be used to allocate a function, but it can be used to allocate pointers to functions. The
following example allocates and then frees an array of seven pointers to functions that return integers.
int (**p) () = new (int (*[7]) ());
delete *p;
If you use the operator new without any extra arguments, and compile with the /GX, /EHa, or /EHs option, the
compiler will generate code to call operator delete if the constructor throws an exception.
The following list describes the grammar elements of new :
placement
Provides a way of passing additional arguments if you overload new .
type-name
Specifies type to be allocated; it can be either a built-in or user-defined type. If the type specification is
complicated, it can be surrounded by parentheses to force the order of binding.
initializer
Provides a value for the initialized object. Initializers cannot be specified for arrays. The new operator will create
arrays of objects only if the class has a default constructor.
// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>
class CName {
public:
enum {
sizeOfBuffer = 256
};
char m_szFirst[sizeOfBuffer];
char m_szLast[sizeOfBuffer];
public:
void SetName(char* pszFirst, char* pszLast) {
strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
strcpy_s(m_szLast, sizeOfBuffer, pszLast);
}
};
int main() {
// Allocate memory for the array
char* pCharArray = new char[CName::sizeOfBuffer];
strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");
// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
A(int) { throw "Fail!"; }
};
void F(void) {
try {
// heap memory pointed to by pa1 will be deallocated
// by calling ::operator delete(void*).
A* pa1 = new A(10);
} catch (...) {
}
try {
// This will call ::operator new(size_t, char*, int).
// When A::A(int) does a throw, we should call
// ::operator delete(void*, char*, int) to deallocate
// the memory pointed to by pa2. Since
// ::operator delete(void*, char*, int) has not been implemented,
// memory will be leaked when the deallocation cannot occur.
int main() {
A a;
}
// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
// Define default constructor and a constructor that accepts
// an initial balance.
Acct() { balance = 0.0; }
Acct( double init_balance ) { balance = init_balance; }
private:
double balance;
};
int main()
{
Acct *CheckingAcct = new Acct;
Acct *SavingsAcct = new Acct ( 34.98 );
double *HowMuch = new double ( 43.0 );
// ...
}
In this example, the object CheckingAcct is allocated using the new operator, but no default initialization is
specified. Therefore, the default constructor for the class, Acct() , is called. Then the object SavingsAcct is
allocated the same way, except that it is explicitly initialized to 34.98. Because 34.98 is of type double , the
constructor that takes an argument of that type is called to handle the initialization. Finally, the nonclass type
HowMuch is initialized to 43.0.
If an object is of a class type and that class has constructors (as in the preceding example), the object can be
initialized by the new operator only if one of these conditions is met:
The arguments provided in the initializer agree with those of a constructor.
The class has a default constructor (a constructor that can be called with no arguments).
No explicit per-element initialization can be done when allocating arrays using the new operator; only the
default constructor, if present, is called. See Default Arguments for more information.
If the memory allocation fails (operator new returns a value of 0), no initialization is performed. This protects
against attempts to initialize data that does not exist.
As with function calls, the order in which initialized expressions are evaluated is not defined. Furthermore, you
should not rely on these expressions being completely evaluated before the memory allocation is performed. If
the memory allocation fails and the new operator returns zero, some expressions in the initializer may not be
completely evaluated.
// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
// Use new operator to allocate an array of 20 characters.
char *AnArray = new char[20];
Once the pointer AnotherArray goes out of scope in the example, the object can no longer be deleted.
NOTE
The argument to operator new is of type size_t . This type is defined in <direct.h>, <malloc.h>, <memory.h>,
<search.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, and <time.h>.
An option in the grammar allows specification of placement (see the Grammar for new Operator). The
placement parameter can be used only for user-defined implementations of operator new ; it allows extra
information to be passed to operator new . An expression with a placement field such as
T *TObject = new ( 0x0040 ) T; is translated to T *TObject = T::operator new( sizeof( T ), 0x0040 ); if class T
has member operator new, otherwise to T *TObject = ::operator new( sizeof( T ), 0x0040 ); .
The original intention of the placement field was to allow hardware-dependent objects to be allocated at user-
specified addresses.
NOTE
Although the preceding example shows only one argument in the placement field, there is no restriction on how many
extra arguments can be passed to operator new this way.
Even when operator new has been defined for a class type, the global operator can be used by using the form
of this example:
See also
Expressions with Unary Operators
Keywords
new and delete operators
One's complement operator: ~
11/2/2020 • 2 minutes to read • Edit Online
Syntax
~ cast-expression
Remarks
The one's complement operator ( ~ ), sometimes called the bitwise complement operator, yields a bitwise one's
complement of its operand. That is, every bit that is 1 in the operand is 0 in the result. Conversely, every bit that
is 0 in the operand is 1 in the result. The operand to the one's complement operator must be an integral type.
Example
// expre_One_Complement_Operator.cpp
// compile with: /EHsc
#include <iostream>
int main () {
unsigned short y = 0xFFFF;
cout << hex << y << endl;
y = ~y; // Take one's complement
cout << hex << y << endl;
}
In this example, the new value assigned to y is the one's complement of the unsigned value 0xFFFF, or 0x0000.
Integral promotion is performed on integral operands. The type the operand is promoted to is the resultant type.
For more information on integral promotion, see Standard conversions.
See also
Expressions with unary operators
C++ built-in operators, precedence, and associativity
Unary arithmetic operators
Pointer-to-Member Operators: .* and ->*
3/6/2021 • 2 minutes to read • Edit Online
Syntax
expression .* expression
expression ->* expression
Remarks
The pointer-to-member operators, .* and ->*, return the value of a specific class member for the object specified
on the left side of the expression. The right side must specify a member of the class. The following example
shows how to use these operators:
// expre_Expressions_with_Pointer_Member_Operators.cpp
// compile with: /EHsc
#include <iostream>
class Testpm {
public:
void m_func1() { cout << "m_func1\n"; }
int m_num;
};
int main() {
Testpm ATestpm;
Testpm *pTestpm = new Testpm;
Output
m_func1
m_func1
1
2
In the preceding example, a pointer to a member, pmfn , is used to invoke the member function m_func1 .
Another pointer to a member, pmd , is used to access the m_num member.
The binary operator .* combines its first operand, which must be an object of class type, with its second operand,
which must be a pointer-to-member type.
The binary operator ->* combines its first operand, which must be a pointer to an object of class type, with its
second operand, which must be a pointer-to-member type.
In an expression containing the .* operator, the first operand must be of the class type of, and be accessible to,
the pointer to member specified in the second operand or of an accessible type unambiguously derived from
and accessible to that class.
In an expression containing the ->* operator, the first operand must be of the type "pointer to the class type" of
the type specified in the second operand, or it must be of a type unambiguously derived from that class.
Example
Consider the following classes and program fragment:
// expre_Expressions_with_Pointer_Member_Operators2.cpp
// C2440 expected
class BaseClass {
public:
BaseClass(); // Base class constructor.
void Func1();
};
int main() {
BaseClass ABase;
Derived ADerived;
The result of the .* or ->* pointer-to-member operators is an object or function of the type specified in the
declaration of the pointer to member. So, in the preceding example, the result of the expression
ADerived.*pmfnFunc1() is a pointer to a function that returns void. This result is an l-value if the second operand
is an l-value.
NOTE
If the result of one of the pointer-to-member operators is a function, then the result can be used only as an operand to
the function call operator.
See also
C++ Built-in Operators, Precedence and Associativity
Postfix Increment and Decrement Operators: ++
and --
3/6/2021 • 2 minutes to read • Edit Online
Syntax
postfix-expression ++
postfix-expression --
Remarks
C++ provides prefix and postfix increment and decrement operators; this section describes only the postfix
increment and decrement operators. (For more information, see Prefix Increment and Decrement Operators.)
The difference between the two is that in the postfix notation, the operator appears after postfix-expression,
whereas in the prefix notation, the operator appears before expression. The following example shows a postfix-
increment operator:
i++;
The effect of applying the postfix increment operator (++ ) is that the operand's value is increased by one unit of
the appropriate type. Similarly, the effect of applying the postfix decrement operator (-- ) is that the operand's
value is decreased by one unit of the appropriate type.
It is important to note that a postfix increment or decrement expression evaluates to the value of the expression
prior to application of the respective operator. The increment or decrement operation occurs after the operand is
evaluated. This issue arises only when the postfix increment or decrement operation occurs in the context of a
larger expression.
When a postfix operator is applied to a function argument, the value of the argument is not guaranteed to be
incremented or decremented before it is passed to the function. See section 1.9.17 in the C++ standard for more
information.
Applying the postfix increment operator to a pointer to an array of objects of type long actually adds four to
the internal representation of the pointer. This behavior causes the pointer, which previously referred to the nth
element of the array, to refer to the (n+1)th element.
The operands to postfix increment and postfix decrement operators must be modifiable (not const ) l-values of
arithmetic or pointer type. The type of the result is the same as that of the postfix-expression, but it is no longer
an l-value.
Visual Studio 2017 version 15.3 and later (available with /std:c++17): The operand of a postfix increment
or decrement operator may not be of type bool .
The following code illustrates the postfix increment operator:
// expre_Postfix_Increment_and_Decrement_Operators.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main() {
int i = 10;
cout << i++ << endl;
cout << i << endl;
}
See also
Postfix Expressions
C++ Built-in Operators, Precedence and Associativity
C Postfix Increment and Decrement Operators
Prefix Increment and Decrement Operators: ++ and
--
3/6/2021 • 2 minutes to read • Edit Online
Syntax
++ unary-expression
-- unary-expression
Remarks
The prefix increment operator (++ ) adds one to its operand; this incremented value is the result of the
expression. The operand must be an l-value not of type const . The result is an l-value of the same type as the
operand.
The prefix decrement operator (-- ) is analogous to the prefix increment operator, except that the operand is
decremented by one and the result is this decremented value.
Visual Studio 2017 version 15.3 and later (available with /std:c++17): The operand of an increment or
decrement operator may not be of type bool .
Both the prefix and postfix increment and decrement operators affect their operands. The key difference
between them is the order in which the increment or decrement takes place in the evaluation of an expression.
(For more information, see Postfix Increment and Decrement Operators.) In the prefix form, the increment or
decrement takes place before the value is used in expression evaluation, so the value of the expression is
different from the value of the operand. In the postfix form, the increment or decrement takes place after the
value is used in expression evaluation, so the value of the expression is the same as the value of the operand.
For example, the following program prints " ++i = 6 ":
// expre_Increment_and_Decrement_Operators.cpp
// compile with: /EHsc
#include <iostream>
int main() {
int i = 5;
cout << "++i = " << ++i << endl;
}
An operand of integral or floating type is incremented or decremented by the integer value 1. The type of the
result is the same as the operand type. An operand of pointer type is incremented or decremented by the size of
the object it addresses. An incremented pointer points to the next object; a decremented pointer points to the
previous object.
Because increment and decrement operators have side effects, using expressions with increment or decrement
operators in a preprocessor macro can have undesirable results. Consider this example:
// expre_Increment_and_Decrement_Operators2.cpp
#define max(a,b) ((a)<(b))?(b):(a)
int main()
{
int i = 0, j = 0, k;
k = max( ++i, j );
}
k = ((++i)<(j))?(j):(++i);
NOTE
C++ inline functions are preferable to macros in many cases because they eliminate side effects such as those described
here, and allow the language to perform more complete type checking.
See also
Expressions with Unary Operators
C++ Built-in Operators, Precedence and Associativity
Prefix Increment and Decrement Operators
Relational Operators: <, >, <=, and >=
3/6/2021 • 2 minutes to read • Edit Online
Syntax
expression < expression
expression > expression
expression <= expression
expression >= expression
Remarks
The binary relational operators determine the following relationships:
Less than (< )
Greater than (> )
Less than or equal to (<= )
Greater than or equal to (>= )
The relational operators have left-to-right associativity. Both operands of relational operators must be of
arithmetic or pointer type. They yield values of type bool . The value returned is false (0) if the relationship in
the expression is false; otherwise, the value returned is true (1).
Example
// expre_Relational_Operators.cpp
// compile with: /EHsc
#include <iostream>
int main() {
cout << "The true expression 3 > 2 yields: "
<< (3 > 2) << endl
<< "The false expression 20 < 10 yields: "
<< (20 < 10) << endl;
}
The expressions in the preceding example must be enclosed in parentheses because the stream insertion
operator (<< ) has higher precedence than the relational operators. Therefore, the first expression without the
parentheses would be evaluated as:
(cout << "The true expression 3 > 2 yields: " << 3) < (2 << "\n");
The usual arithmetic conversions covered in Standard Conversions are applied to operands of arithmetic types.
Comparing pointers
When two pointers to objects of the same type are compared, the result is determined by the location of the
objects pointed to in the program's address space. Pointers can also be compared to a constant expression that
evaluates to 0 or to a pointer of type void * . If a pointer comparison is made against a pointer of type void * ,
the other pointer is implicitly converted to type void * . Then the comparison is made.
Two pointers of different types cannot be compared unless:
One type is a class type derived from the other type.
At least one of the pointers is explicitly converted (cast) to type void * . (The other pointer is implicitly
converted to type void * for the conversion.)
Two pointers of the same type that point to the same object are guaranteed to compare equal. If two pointers to
nonstatic members of an object are compared, the following rules apply:
If the class type is not a union , and if the two members are not separated by an access-specifier, such as
public , protected , or private , the pointer to the member declared last will compare greater than the
pointer to the member declared earlier.
If the two members are separated by an access-specifier, the results are undefined.
If the class type is a union , pointers to different data members in that union compare equal.
If two pointers point to elements of the same array or to the element one beyond the end of the array, the
pointer to the object with the higher subscript compares higher. Comparison of pointers is guaranteed valid only
when the pointers refer to objects in the same array or to the location one past the end of the array.
See also
Expressions with Binary Operators
C++ Built-in Operators, Precedence and Associativity
C Relational and Equality Operators
Scope resolution operator: ::
3/6/2021 • 2 minutes to read • Edit Online
The scope resolution operator :: is used to identify and disambiguate identifiers used in different scopes. For
more information about scope, see Scope.
Syntax
qualified-id :
nested-name-specifier template opt unqualified-id
nested-name-specifier :
::
type-name ::
namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier template opt simple-template-id ::
unqualified-id :
identifier
operator-function-id
conversion-function-id
literal-operator-id
~ type-name
~ decltype-specifier
template-id
Remarks
The identifier can be a variable, a function, or an enumeration value.
int main() {
A scope resolution operator without a scope qualifier refers to the global namespace.
namespace NamespaceA{
int x;
}
int x;
int main() {
int x;
// the x in main()
x = 0;
// The x in the global namespace
::x = 1;
You can use the scope resolution operator to identify a member of a namespace , or to identify a namespace that
nominates the member’s namespace in a using directive. In the example below, you can use NamespaceC to
qualify ClassB , even though ClassB was declared in namespace NamespaceB , because NamespaceB was
nominated in NamespaceC by a using directive.
namespace NamespaceB {
class ClassB {
public:
int x;
};
}
namespace NamespaceC{
using namespace NamespaceB;
}
int main() {
NamespaceB::ClassB b_b;
NamespaceC::ClassB c_b;
b_b.x = 3;
c_b.x = 4;
}
You can use chains of scope resolution operators. In the following example, NamespaceD::NamespaceD1 identifies
the nested namespace NamespaceD1 , and NamespaceE::ClassE::ClassE1 identifies the nested class ClassE1 .
namespace NamespaceD{
namespace NamespaceD1{
int x;
}
}
namespace NamespaceE{
class ClassE{
public:
class ClassE1{
public:
int x;
};
};
}
int main() {
NamespaceD:: NamespaceD1::x = 6;
NamespaceE::ClassE::ClassE1 e1;
e1.x = 7 ;
}
class ClassG {
public:
static int get_x() { return x;}
static int x;
};
int ClassG::x = 6;
int main() {
int main() {
EnumA enum_value = EnumA::First;
}
See also
C++ built-in operators, precedence, and associativity
Namespaces
sizeof Operator
3/6/2021 • 2 minutes to read • Edit Online
Yields the size of its operand with respect to the size of type char .
NOTE
For information about the sizeof ... operator, see Ellipsis and variadic templates.
Syntax
sizeof unary-expression
sizeof ( type-name )
Remarks
The result of the sizeof operator is of type size_t , an integral type defined in the include file <stddef.h>. This
operator allows you to avoid specifying machine-dependent data sizes in your programs.
The operand to sizeof can be one of the following:
A type name. To use sizeof with a type name, the name must be enclosed in parentheses.
An expression. When used with an expression, sizeof can be specified with or without the parentheses.
The expression is not evaluated.
When the sizeof operator is applied to an object of type char , it yields 1. When the sizeof operator is
applied to an array, it yields the total number of bytes in that array, not the size of the pointer represented by the
array identifier. To obtain the size of the pointer represented by the array identifier, pass it as a parameter to a
function that uses sizeof . For example:
Example
#include <iostream>
using namespace std;
int main()
{
char szHello[] = "Hello, world!";
When the sizeof operator is applied to a class , struct , or union type, the result is the number of bytes in
an object of that type, plus any padding added to align members on word boundaries. The result does not
necessarily correspond to the size calculated by adding the storage requirements of the individual members.
The /Zp compiler option and the pack pragma affect alignment boundaries for members.
The sizeof operator never yields 0, even for an empty class.
The sizeof operator cannot be used with the following operands:
Functions. (However, sizeof can be applied to pointers to functions.)
Bit fields.
Undefined classes.
The type void .
Dynamically allocated arrays.
External arrays.
Incomplete types.
Parenthesized names of incomplete types.
When the sizeof operator is applied to a reference, the result is the same as if sizeof had been applied to the
object itself.
If an unsized array is the last element of a structure, the sizeof operator returns the size of the structure
without the array.
The sizeof operator is often used to calculate the number of elements in an array using an expression of the
form:
See also
Expressions with Unary Operators
Keywords
Subscript Operator []
3/6/2021 • 3 minutes to read • Edit Online
Syntax
postfix-expression [ expression ]
Remarks
A postfix expression (which can also be a primary expression) followed by the subscript operator, [ ] , specifies
array indexing.
For information about managed arrays in C++/CLI, see Arrays.
Usually, the value represented by postfix-expression is a pointer value, such as an array identifier, and expression
is an integral value (including enumerated types). However, all that is required syntactically is that one of the
expressions be of pointer type and the other be of integral type. Thus the integral value could be in the postfix-
expression position and the pointer value could be in the brackets in the expression or subscript position.
Consider the following code fragment:
int nArray[5] = { 0, 1, 2, 3, 4 };
cout << nArray[2] << endl; // prints "2"
cout << 2[nArray] << endl; // prints "2"
In the preceding example, the expression nArray[2] is identical to 2[nArray] . The reason is that the result of a
subscript expression e1[e2] is given by:
*((e2) + (e1))
The address yielded by the expression is not e2 bytes from the address e1. Rather, the address is scaled to yield
the next object in the array e2. For example:
double aDbl[2];
The addresses of aDb[0] and aDb[1] are 8 bytes apart — the size of an object of type double . This scaling
according to object type is done automatically by the C++ language and is defined in Additive Operators where
addition and subtraction of operands of pointer type is discussed.
A subscript expression can also have multiple subscripts, as follows:
expression1 [ expression2 ] [ expression3 ] ...
Subscript expressions associate from left to right. The leftmost subscript expression, expression1 [ expression2 ] ,
is evaluated first. The address that results from adding expression1 and expression2 forms a pointer expression;
then expression3 is added to this pointer expression to form a new pointer expression, and so on until the last
subscript expression has been added. The indirection operator (* ) is applied after the last subscripted expression
is evaluated, unless the final pointer value addresses an array type.
Expressions with multiple subscripts refer to elements of multidimensional arrays. A multidimensional array is
an array whose elements are arrays. For example, the first element of a three-dimensional array is an array with
two dimensions. The following example declares and initializes a simple two-dimensional array of characters:
// expre_Subscript_Operator.cpp
// compile with: /EHsc
#include <iostream>
int main() {
char c[ MAX_ROWS ][ MAX_COLS ] = { { 'a', 'b' }, { 'c', 'd' } };
for ( int i = 0; i < MAX_ROWS; i++ )
for ( int j = 0; j < MAX_COLS; j++ )
cout << c[ i ][ j ] << endl;
}
#include <iostream>
using namespace std;
int main() {
int intArray[1024];
for (int i = 0, j = 0; i < 1024; i++)
{
intArray[i] = j++;
}
The negative subscript in the last line can produce a run-time error because it points to an address 256 int
positions lower in memory than the origin of the array. The pointer midArray is initialized to the middle of
intArray ; it is therefore possible (but dangerous) to use both positive and negative array indices on it. Array
subscript errors do not generate compile-time errors, but they yield unpredictable results.
The subscript operator is commutative. Therefore, the expressions array[index] and index[array] are guaranteed
to be equivalent as long as the subscript operator is not overloaded (see Overloaded Operators). The first form
is the most common coding practice, but either works.
See also
Postfix Expressions
C++ Built-in Operators, Precedence and Associativity
Arrays
One-Dimensional Arrays
Multidimensional Arrays
typeid Operator
3/6/2021 • 2 minutes to read • Edit Online
Syntax
typeid(type-id)
typeid(expression)
Remarks
The typeid operator allows the type of an object to be determined at run time.
The result of typeid is a const type_info& . The value is a reference to a type_info object that represents either
the type-id or the type of the expression, depending on which form of typeid is used. For more information,
see type_info Class.
The typeid operator doesn't work with managed types (abstract declarators or instances). For information on
getting the Type of a specified type, see typeid.
The typeid operator does a run-time check when applied to an l-value of a polymorphic class type, where the
true type of the object can't be determined by the static information provided. Such cases are:
A reference to a class
A pointer, dereferenced with *
A subscripted pointer ( [ ] ). (It's not safe to use a subscript with a pointer to a polymorphic type.)
If the expression points to a base class type, yet the object is actually of a type derived from that base class, a
type_info reference for the derived class is the result. The expression must point to a polymorphic type (a class
with virtual functions). Otherwise, the result is the type_info for the static class referred to in the expression.
Further, the pointer must be dereferenced so that the object used is the one it points to. Without dereferencing
the pointer, the result will be the type_info for the pointer, not what it points to. For example:
// expre_typeid_Operator.cpp
// compile with: /GR /EHsc
#include <iostream>
#include <typeinfo>
class Base {
public:
virtual void vvfunc() {}
};
If the expression is dereferencing a pointer, and that pointer's value is zero, typeid throws a bad_typeid
exception. If the pointer doesn't point to a valid object, a __non_rtti_object exception is thrown. It indicates an
attempt to analyze the RTTI that triggered a fault because the object is somehow invalid. (For example, it's a bad
pointer, or the code wasn't compiled with /GR).
If the expression is not a pointer, and not a reference to a base class of the object, the result is a type_info
reference representing the static type of the expression. The static type of an expression refers to the type of an
expression as it is known at compile time. Execution semantics are ignored when evaluating the static type of an
expression. Furthermore, references are ignored when possible when determining the static type of an
expression:
// expre_typeid_Operator_2.cpp
#include <typeinfo>
int main()
{
typeid(int) == typeid(int&); // evaluates to true
}
typeid can also be used in templates to determine the type of a template parameter:
// expre_typeid_Operator_3.cpp
// compile with: /c
#include <typeinfo>
template < typename T >
T max( T arg1, T arg2 ) {
cout << typeid( T ).name() << "s compared." << endl;
return ( arg1 > arg2 ? arg1 : arg2 );
}
See also
Run-Time Type Information
Keywords
Unary Plus and Negation Operators: + and -
3/6/2021 • 2 minutes to read • Edit Online
Syntax
+ cast-expression
- cast-expression
+ operator
The result of the unary plus operator (+ ) is the value of its operand. The operand to the unary plus operator
must be of an arithmetic type.
Integral promotion is performed on integral operands. The resultant type is the type to which the operand is
promoted. Thus, the expression +ch , where ch is of type char , results in type int ; the value is unmodified.
See Standard Conversions for more information about how the promotion is done.
- operator
The unary negation operator (- ) produces the negative of its operand. The operand to the unary negation
operator must be an arithmetic type.
Integral promotion is performed on integral operands, and the resultant type is the type to which the operand is
promoted. See Standard Conversions for more information about how the promotion is performed.
Microsoft Specific
Unary negation of unsigned quantities is performed by subtracting the value of the operand from 2^n, where n
is the number of bits in an object of the given unsigned type.
END Microsoft Specific
See also
Expressions with Unary Operators
C++ Built-in Operators, Precedence and Associativity
Expressions (C++)
3/6/2021 • 2 minutes to read • Edit Online
This section describes C++ expressions. Expressions are sequences of operators and operands that are used for
one or more of these purposes:
Computing a value from the operands.
Designating objects or functions.
Generating "side effects." (Side effects are any actions other than the evaluation of the expression — for
example, modifying the value of an object.)
In C++, operators can be overloaded and their meanings can be user-defined. However, their precedence and
the number of operands they take cannot be modified. This section describes the syntax and semantics of
operators as they are supplied with the language, not overloaded. In addition to types of expressions and
semantics of expressions, the following topics are covered:
Primary expressions
Scope resolution operator
Postfix expressions
Expressions with unary operators
Expressions with binary operators
Conditional operator
Constant expressions
Casting operators
Run-time type information
Topics on operators in other sections:
C++ Built-in Operators, Precedence and Associativity
Overloaded operators
typeid (C++/CLI)
NOTE
Operators for built-in types cannot be overloaded; their behavior is predefined.
See also
C++ Language Reference
Types of Expressions
3/6/2021 • 2 minutes to read • Edit Online
See also
Expressions
Primary Expressions
11/2/2020 • 2 minutes to read • Edit Online
Primary expressions are the building blocks of more complex expressions. They may be literals, names, and
names qualified by the scope-resolution operator ( :: ). A primary expression may have any of the following
forms:
primary-expression
literal
this
name
:: name ( expression )
A literal is a constant primary expression. Its type depends on the form of its specification. For complete
information about specifying literals, see Literals .
The this keyword is a pointer to a class object. It's available within nonstatic member functions. It points to the
instance of the class for which the function was invoked. The this keyword can't be used outside the body of a
class-member function.
The type of the this pointer is type * const (where type is the class name) within functions that don't
specifically modify the this pointer. The following example shows member function declarations and the types
of this :
// expre_Primary_Expressions.cpp
// compile with: /LD
class Example
{
public:
void Func(); // * const this
void Func() const; // const * const this
void Func() volatile; // volatile * const this
};
For more information about modifying the type of the this pointer, see this pointer.
The scope-resolution operator ( :: ) followed by a name is a primary expression. Such names must be names at
global scope, not member names. The type of the expression is determined by the declaration of the name. It's
an l-value (that is, it can appear on the left-hand side of an assignment expression) if the declaring name is an l-
value. The scope-resolution operator allows a global name to be referred to, even if that name is hidden in the
current scope. See Scope for an example of how to use the scope-resolution operator.
An expression enclosed in parentheses is a primary expression. Its type and value are identical to the type and
value of the unparenthesized expression. It's an l-value if the unparenthesized expression is an l-value.
Examples of primary expressions include:
100 // literal
'c' // literal
this // in a member function, a pointer to the class instance
::func // a global function
::operator + // a global operator function
::A::B // a global qualified name
( i + 1 ) // a parenthesized expression
These examples are all considered names, and as such, primary expressions, in various forms:
MyClass // an identifier
MyClass::f // a qualified name
operator = // an operator function name
operator char* // a conversion operator function name
~MyClass // a destructor name
A::B // a qualified name
A<int> // a template id
See also
Types of Expressions
Ellipsis and Variadic Templates
3/6/2021 • 3 minutes to read • Edit Online
This article shows how to use the ellipsis ( ... ) with C++ variadic templates. The ellipsis has had many uses in
C and C++. These include variable argument lists for functions. The printf() function from the C Runtime
Library is one of the most well-known examples.
A variadic template is a class or function template that supports an arbitrary number of arguments. This
mechanism is especially useful to C++ library developers because you can apply it to both class templates and
function templates, and thereby provide a wide range of type-safe and non-trivial functionality and flexibility.
Syntax
An ellipsis is used in two ways by variadic templates. To the left of the parameter name, it signifies a parameter
pack, and to the right of the parameter name, it expands the parameter packs into separate names.
Here's a basic example of variadic template class definition syntax:
For both parameter packs and expansions, you can add whitespace around the ellipsis, based on your
preference, as shown in these examples:
Or this:
Notice that this article uses the convention that's shown in the first example (the ellipsis is attached to typename
).
In the preceding examples, Arguments is a parameter pack. The class classname can accept a variable number
of arguments, as in these examples:
By using a variadic template class definition, you can also require at least one parameter:
The Arguments parameter pack is then expanded for use, as shown in the next section, Understanding
variadic templates .
Other forms of variadic template function syntax are possible—including, but not limited to, these examples:
As with variadic template class definitions, you can make functions that require at least one parameter:
template <typename First, typename... Rest> returntype functionname(const First& first, const Rest&...
args);
Variadic templates use the sizeof...() operator (unrelated to the older sizeof() operator):
template<typename... Arguments>
void tfunc(const Arguments&... args)
{
constexpr auto numargs{ sizeof...(Arguments) };
helper_func(xobj, args...);
}
Where the ellipsis appears immediately after a parameter name, you have a parameter pack expansion.
Example
A good way to illustrate the variadic template function mechanism is to use it in a re-write of some of the
functionality of printf :
#include <iostream>
void print() {
cout << endl;
}
template <typename First, typename... Rest> void print(const First& first, const Rest&... rest) {
cout << first << ", ";
print(rest...); // recursive call using pack expansion syntax
}
int main()
{
print(); // calls first overload, outputting only a newline
print(1); // calls second overload
Output
1
10, 20
100, 200, 300
first, 2, third, 3.14159
NOTE
Most implementations that incorporate variadic template functions use recursion of some form, but it's slightly different
from traditional recursion. Traditional recursion involves a function calling itself by using the same signature. (It may be
overloaded or templated, but the same signature is chosen each time.) Variadic recursion involves calling a variadic
function template by using differing (almost always decreasing) numbers of arguments, and thereby stamping out a
different signature every time. A "base case" is still required, but the nature of the recursion is different.
Postfix Expressions
3/6/2021 • 6 minutes to read • Edit Online
Postfix expressions consist of primary expressions or expressions in which postfix operators follow a primary
expression. The postfix operators are listed in the following table.
Postfix Operators
O P ERATO R N A M E O P ERATO R N OTAT IO N
Subscript operator []
primary-expression
postfix-expression[expression]postfix-expression(expression-list)simple-type-name(expression-list)postfix-
expression.namepostfix-expression->namepostfix-expression++postfix-expression--cast-keyword < typename >
(expression )typeid ( typename )
The postfix-expression above may be a primary expression or another postfix expression. Postfix expressions
group left to right, thus allowing the expressions to be chained together as follows:
func(1)->GetValue()++
In the above expression, func is a primary expression, func(1) is a function postfix expression,
func(1)->GetValue is a postfix expression specifying a member of the class, func(1)->GetValue() is another
function postfix expression, and the entire expression is a postfix expression incrementing the return value of
GetValue. The meaning of the expression as a whole is "call func passing 1 as an argument and get a pointer to a
class as a return value. Then call GetValue() on that class, then increment the value returned.
The expressions listed above are assignment expressions, meaning that the result of these expressions must be
an r-value.
The postfix expression form
simple-type-name ( expression-list )
indicates the invocation of the constructor. If the simple-type-name is a fundamental type, the expression list
must be a single expression, and this expression indicates a cast of the expression's value to the fundamental
type. This type of cast expression mimics a constructor. Because this form allows fundamental types and classes
to be constructed using the same syntax, this form is especially useful when defining template classes.
The cast-keyword is one of dynamic_cast , static_cast or reinterpret_cast . More information may be found in
dynamic_cast , static_cast and reinterpet_cast .
int Temp_i = 7;
Func( Temp_i );
Note that the initialization is performed as if using the equal-sign syntax instead of the parentheses
syntax. A copy of i is made prior to passing the value to the function. (For more information, see
Initializers and Conversions).
Therefore, if the function prototype (declaration) calls for an argument of type long , and if the calling
program supplies an actual argument of type int , the actual argument is promoted using a standard
type conversion to type long (see Standard Conversions).
It is an error to supply an actual argument for which there is no standard or user-defined conversion to
the type of the formal argument.
For actual arguments of class type, the formal argument is initialized by calling the class's constructor.
(See Constructors for more about these special class member functions.)
The function call is executed.
The following program fragment demonstrates a function call:
// expre_Formal_and_Actual_Arguments.cpp
void func( long param1, double param2 );
int main()
{
long i = 1;
double j = 2;
When func is called from main, the formal parameter param1 is initialized with the value of i ( i is
converted to type long to correspond to the correct type using a standard conversion), and the formal
parameter param2 is initialized with the value of j ( j is converted to type double using a standard
conversion).
// expre_Treatment_of_Argument_Types.cpp
int func1( const int i, int j, char *c ) {
i = 7; // C3892 i is const.
j = i; // value of j is lost at return
*c = 'a' + j; // changes value of c in calling function
return i;
}
// expre_Ellipsis_and_Default_Arguments.cpp
// compile with: /EHsc
#include <iostream>
int main()
{
print( "hello," );
print( "world!" );
The preceding program declares a function, print , that takes two arguments. However, the second argument,
terminator, has a default value, "\n" . In main , the first two calls to print allow the default second argument
to supply a new line to terminate the printed string. The third call specifies an explicit value for the second
argument. The output from the program is
hello,
world!
good morning, sunshine.
See also
Types of Expressions
Expressions with Unary Operators
3/6/2021 • 2 minutes to read • Edit Online
Unary operators act on only one operand in an expression. The unary operators are as follows:
Indirection operator (*)
Address-of operator (&)
Unary plus operator (+)
Unary negation operator (-)
Logical negation operator (!)
One's complement operator (~)
Prefix increment operator (++)
Prefix decrement operator (--)
Cast operator ()
sizeof operator
__uuidof operator
alignof operator
new operator
delete operator
These operators have right-to-left associativity. Unary expressions generally involve syntax that precedes a
postfix or primary expression.
The following are the possible forms of unary expressions.
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof( type-name )
decltype( expression )
allocation-expression
deallocation-expression
Any postfix-expression is considered a unary-expression, and because any primary expression is considered a
postfix-expression, any primary expressions is considered a unary-expression also. For more information, see
Postfix Expressions and Primary Expressions.
A unary-operator consists of one or more of the following symbols: * & + - ! ~
The cast-expression is a unary expression with an optional cast to change the type. For more information see
Cast Operator: ().
An expression can be any expression. For more information, see Expressions.
The allocation-expression refers to the new operator. The deallocation-expression refers to the delete operator.
For more information, see the links earlier in this topic.
See also
Types of Expressions
Expressions with Binary Operators
3/6/2021 • 2 minutes to read • Edit Online
Binary operators act on two operands in an expression. The binary operators are:
Multiplicative operators
Multiplication (*)
Division (/)
Modulus (%)
Additive operators
Addition (+)
Subtraction (-)
Shift operators
Right shift (>>)
Left shift (<<)
Relational and equality operators
Less than (<)
Greater than (>)
Less than or equal to (<=)
Greater than or equal to (>=)
Equal to (==)
Not equal to (!=)
Bitwise operators
Bitwise AND (&)
Bitwise exclusive OR (^)
Bitwise inclusive OR (|)
Logical operators
Logical AND (&&)
Logical OR (||)
Assignment operators
Assignment (=)
Addition assignment (+=)
Subtraction assignment (-=)
Multiplication assignment (*=)
Division assignment (/=)
Modulus assignment (%=)
Left shift assignment (<<=)
Right shift assignment (>>=)
Bitwise AND assignment (&=)
Bitwise exclusive OR assignment (^=)
Bitwise inclusive OR assignment (|=)
Comma Operator (,)
See also
Types of Expressions
C++ Constant Expressions
3/6/2021 • 2 minutes to read • Edit Online
A constant value is one that doesn't change. C++ provides two keywords to enable you to express the intent that
an object is not intended to be modified, and to enforce that intent.
C++ requires constant expressions — expressions that evaluate to a constant — for declarations of:
Array bounds
Selectors in case statements
Bit-field length specification
Enumeration initializers
The only operands that are legal in constant expressions are:
Literals
Enumeration constants
Values declared as const that are initialized with constant expressions
sizeof expressions
Nonintegral constants must be converted (either explicitly or implicitly) to integral types to be legal in a constant
expression. Therefore, the following code is legal:
Explicit conversions to integral types are legal in constant expressions; all other types and derived types are
illegal except when used as operands to the sizeof operator.
The comma operator and assignment operators cannot be used in constant expressions.
See also
Types of Expressions
Semantics of Expressions
3/6/2021 • 4 minutes to read • Edit Online
Expressions are evaluated according to the precedence and grouping of their operators. (Operator Precedence
and Associativity in Lexical Conventions, shows the relationships the C++ operators impose on expressions.)
Order of evaluation
Consider this example:
// Order_of_Evaluation.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
int a = 2, b = 4, c = 9;
38
38
54
Expression-evaluation order
The order in which the expression shown in the above figure is evaluated is determined by the precedence and
associativity of the operators:
1. Multiplication (*) has the highest precedence in this expression; hence the subexpression b * c is
evaluated first.
2. Addition (+) has the next highest precedence, so a is added to the product of b and c .
3. Left shift (<<) has the lowest precedence in the expression, but there are two occurrences. Because the
left-shift operator groups left-to-right, the left subexpression is evaluated first and then the right one.
When parentheses are used to group the subexpressions, they alter the precedence and also the order in which
the expression is evaluated, as shown in the following figure.
Notation in expressions
The C++ language specifies certain compatibilities when specifying operands. The following table shows the
types of operands acceptable to operators that require operands of type type.
Operand Types Acceptable to Operators
T Y P E EXP EC T ED T Y P ES A L LO W ED
type * type *
const type *
volatile type *
volatile const type *
Because the preceding rules can always be used in combination, a const pointer to a volatile object can be
supplied where a pointer is expected.
Ambiguous expressions
Certain expressions are ambiguous in their meaning. These expressions occur most frequently when an object's
value is modified more than once in the same expression. These expressions rely on a particular order of
evaluation where the language does not define one. Consider the following example:
int i = 7;
func( i, ++i );
The C++ language does not guarantee the order in which arguments to a function call are evaluated. Therefore,
in the preceding example, func could receive the values 7 and 8, or 8 and 8 for its parameters, depending on
whether the parameters are evaluated from left to right or from right to left.
See also
Expressions
Casting
3/6/2021 • 2 minutes to read • Edit Online
The C++ language provides that if a class is derived from a base class containing virtual functions, a pointer to
that base class type can be used to call the implementations of the virtual functions residing in the derived class
object. A class containing virtual functions is sometimes called a "polymorphic class."
Since a derived class completely contains the definitions of all the base classes from which it is derived, it is safe
to cast a pointer up the class hierarchy to any of these base classes. Given a pointer to a base class, it might be
safe to cast the pointer down the hierarchy. It is safe if the object being pointed to is actually of a type derived
from the base class. In this case, the actual object is said to be the "complete object." The pointer to the base
class is said to point to a "subobject" of the complete object. For example, consider the class hierarchy shown in
the following figure.
Class hierarchy
An object of type C could be visualized as shown in the following figure.
See also
Expressions
Casting Operators
3/6/2021 • 2 minutes to read • Edit Online
There are several casting operators specific to the C++ language. These operators are intended to remove some
of the ambiguity and danger inherent in old style C language casts. These operators are:
dynamic_cast Used for conversion of polymorphic types.
static_cast Used for conversion of nonpolymorphic types.
const_cast Used to remove the const , volatile , and __unaligned attributes.
reinterpret_cast Used for simple reinterpretation of bits.
safe_cast Used in C++/CLI to produce verifiable MSIL.
Use const_cast and reinterpret_cast as a last resort, since these operators present the same dangers as old
style casts. However, they are still necessary in order to completely replace old style casts.
See also
Casting
dynamic_cast Operator
11/2/2020 • 7 minutes to read • Edit Online
Syntax
dynamic_cast < type-id > ( expression )
Remarks
The type-id must be a pointer or a reference to a previously defined class type or a "pointer to void". The type
of expression must be a pointer if type-id is a pointer, or an l-value if type-id is a reference.
See static_cast for an explanation of the difference between static and dynamic casting conversions, and when it
is appropriate to use each.
There are two breaking changes in the behavior of dynamic_cast in managed code:
dynamic_cast to a pointer to the underlying type of a boxed enum will fail at runtime, returning 0 instead
of the converted pointer.
dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with
the cast failing at runtime. The cast will now return the 0 pointer value instead of throwing.
If type-id is a pointer to an unambiguous accessible direct or indirect base class of expression , a pointer to the
unique subobject of type type-id is the result. For example:
// dynamic_cast_1.cpp
// compile with: /c
class B { };
class C : public B { };
class D : public C { };
This type of conversion is called an "upcast" because it moves a pointer up a class hierarchy, from a derived class
to a class it is derived from. An upcast is an implicit conversion.
If type-id is void*, a run-time check is made to determine the actual type of expression . The result is a pointer
to the complete object pointed to by expression . For example:
// dynamic_cast_2.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
void f() {
A* pa = new A;
B* pb = new B;
void* pv = dynamic_cast<void*>(pa);
// pv now points to an object of type A
pv = dynamic_cast<void*>(pb);
// pv now points to an object of type B
}
If type-id is not void*, a run-time check is made to see if the object pointed to by expression can be converted
to the type pointed to by type-id .
If the type of expression is a base class of the type of type-id , a run-time check is made to see if expression
actually points to a complete object of the type of type-id . If this is true, the result is a pointer to a complete
object of the type of type-id . For example:
// dynamic_cast_3.cpp
// compile with: /c /GR
class B {virtual void f();};
class D : public B {virtual void f();};
void f() {
B* pb = new D; // unclear but ok
B* pb2 = new B;
This type of conversion is called a "downcast" because it moves a pointer down a class hierarchy, from a given
class to a class derived from it.
In cases of multiple inheritance, possibilities for ambiguity are introduced. Consider the class hierarchy shown in
the following figure.
For CLR types, dynamic_cast results in either a no-op if the conversion can be performed implicitly, or an MSIL
isinst instruction, which performs a dynamic check and returns nullptr if the conversion fails.
The following sample uses dynamic_cast to determine if a class is an instance of particular type:
// dynamic_cast_clr.cpp
// compile with: /clr
using namespace System;
int main() {
Object^o1 = "hello";
Object^o2 = 10;
PrintObjectType(o1);
PrintObjectType(o2);
}
// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A {virtual void f();};
class D : public B, public C {virtual void f();};
void f() {
D* pd = new D;
A* pa = dynamic_cast<A*>(pd); // C4540, ambiguous cast fails at runtime
B* pb = dynamic_cast<B*>(pd); // first cast to B
A* pa2 = dynamic_cast<A*>(pb); // ok: unambiguous
}
Further ambiguities can be introduced when you use virtual base classes. Consider the class hierarchy shown in
the following figure.
// dynamic_cast_5.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};
The dynamic_cast operator can also be used to perform a "cross cast." Using the same class hierarchy, it is
possible to cast a pointer, for example, from the B subobject to the D subobject, as long as the complete object
is of type E .
Considering cross casts, it is actually possible to do the conversion from a pointer to D to a pointer to the left-
most A subobject in just two steps. You can perform a cross cast from D to B , then an implicit conversion
from B to A . For example:
// dynamic_cast_6.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};
A null pointer value is converted to the null pointer value of the destination type by dynamic_cast .
When you use dynamic_cast < type-id > ( expression ) , if expression cannot be safely converted to type
type-id , the run-time check causes the cast to fail. For example:
// dynamic_cast_7.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
void f() {
A* pa = new A;
B* pb = dynamic_cast<B*>(pa); // fails at runtime, not safe;
// B not derived from A
}
The value of a failed cast to pointer type is the null pointer. A failed cast to reference type throws a bad_cast
Exception. If expression does not point to or reference a valid object, a __non_rtti_object exception is thrown.
See typeid for an explanation of the __non_rtti_object exception.
Example
The following sample creates the base class (struct A) pointer, to an object (struct C). This, plus the fact there are
virtual functions, enables runtime polymorphism.
The sample also calls a non-virtual function in the hierarchy.
// dynamic_cast_8.cpp
// compile with: /GR /EHsc
#include <stdio.h>
#include <iostream>
struct A {
virtual void test() {
printf_s("in A\n");
}
};
struct B : A {
virtual void test() {
printf_s("in B\n");
}
void test2() {
printf_s("test2 in B\n");
}
};
struct C : B {
virtual void test() {
printf_s("in C\n");
}
void test2() {
printf_s("test2 in C\n");
}
};
void Globaltest(A& a) {
try {
C &c = dynamic_cast<C&>(a);
printf_s("in GlobalTest\n");
}
catch(std::bad_cast) {
printf_s("Can't cast to C\n");
}
}
int main() {
A *pa = new C;
A *pa2 = new B;
pa->test();
B * pb = dynamic_cast<B *>(pa);
if (pb)
pb->test2();
C * pc = dynamic_cast<C *>(pa2);
if (pc)
pc->test2();
C ConStack;
Globaltest(ConStack);
See also
Casting Operators
Keywords
bad_cast exception
3/6/2021 • 2 minutes to read • Edit Online
The bad_cast exception is thrown by the dynamic_cast operator as the result of a failed cast to a reference type.
Syntax
catch (bad_cast)
statement
Remarks
The interface for bad_cast is:
The following code contains an example of a failed dynamic_cast that throws the bad_cast exception.
// expre_bad_cast_Exception.cpp
// compile with: /EHsc /GR
#include <typeinfo>
#include <iostream>
class Shape {
public:
virtual void virtualfunc() const {}
};
The exception is thrown because the object being cast (a Shape) isn't derived from the specified cast type
(Circle). To avoid the exception, add these declarations to main :
Circle circle_instance;
Circle& ref_circle = circle_instance;
Then reverse the sense of the cast in the try block as follows:
Shape& ref_shape = dynamic_cast<Shape&>(ref_circle);
Members
Constructors
C O N ST RUC TO R DESC RIP T IO N
Functions
F UN C T IO N DESC RIP T IO N
what TBD
Operators
O P ERATO R DESC RIP T IO N
bad_cast
The constructor for objects of type bad_cast .
operator=
An assignment operator that assigns one bad_cast object to another.
what
const char* what() const noexcept override;
See also
dynamic_cast Operator
Keywords
Modern C++ best practices for exceptions and error handling
static_cast Operator
3/6/2021 • 4 minutes to read • Edit Online
Converts an expression to the type of type-id, based only on the types that are present in the expression.
Syntax
static_cast <type-id> ( expression )
Remarks
In standard C++, no run-time type check is made to help ensure the safety of the conversion. In C++/CX, a
compile time and runtime check are performed. For more information, see Casting.
The static_cast operator can be used for operations such as converting a pointer to a base class to a pointer to
a derived class. Such conversions are not always safe.
In general you use static_cast when you want to convert numeric data types such as enums to ints or ints to
floats, and you are certain of the data types involved in the conversion. static_cast conversions are not as safe
as dynamic_cast conversions, because static_cast does no run-time type check, while dynamic_cast does. A
dynamic_cast to an ambiguous pointer will fail, while a static_cast returns as if nothing were wrong; this can
be dangerous. Although dynamic_cast conversions are safer, dynamic_cast only works on pointers or
references, and the run-time type check is an overhead. For more information, see dynamic_cast Operator.
In the example that follows, the line D* pd2 = static_cast<D*>(pb); is not safe because D can have fields and
methods that are not in B . However, the line B* pb2 = static_cast<B*>(pd); is a safe conversion because D
always contains all of B .
// static_cast_Operator.cpp
// compile with: /LD
class B {};
In contrast to dynamic_cast, no run-time check is made on the static_cast conversion of pb . The object
pointed to by pb may not be an object of type D , in which case the use of *pd2 could be disastrous. For
instance, calling a function that is a member of the D class, but not the B class, could result in an access
violation.
The dynamic_cast and static_cast operators move a pointer throughout a class hierarchy. However,
static_cast relies exclusively on the information provided in the cast statement and can therefore be unsafe.
For example:
// static_cast_Operator_2.cpp
// compile with: /LD /GR
class B {
public:
virtual void Test(){}
};
class D : public B {};
If pb really points to an object of type D , then pd1 and pd2 will get the same value. They will also get the
same value if pb == 0 .
If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to
return zero. However, static_cast relies on the programmer's assertion that pb points to an object of type D
and simply returns a pointer to that supposed D object.
Consequently, static_cast can do the inverse of implicit conversions, in which case the results are undefined. It
is left to the programmer to verify that the results of a static_cast conversion are safe.
This behavior also applies to types other than class types. For instance, static_cast can be used to convert
from an int to a char . However, the resulting char may not have enough bits to hold the entire int value.
Again, it is left to the programmer to verify that the results of a static_cast conversion are safe.
The static_cast operator can also be used to perform any implicit conversion, including standard conversions
and user-defined conversions. For example:
// static_cast_Operator_3.cpp
// compile with: /LD /GR
typedef unsigned char BYTE;
void f() {
char ch;
int i = 65;
float f = 2.5;
double dbl;
The static_cast operator can explicitly convert an integral value to an enumeration type. If the value of the
integral type does not fall within the range of enumeration values, the resulting enumeration value is undefined.
The static_cast operator converts a null pointer value to the null pointer value of the destination type.
Any expression can be explicitly converted to type void by the static_cast operator. The destination void type
can optionally include the const , volatile , or __unaligned attribute.
The static_cast operator cannot cast away the const , volatile , or __unaligned attributes. See const_cast
Operator for information on removing these attributes.
C++/CLI: Due to the danger of performing unchecked casts on top of a relocating garbage collector, the use of
static_cast should only be in performance-critical code when you are certain it will work correctly. If you must
use static_cast in release mode, substitute it with safe_cast in your debug builds to ensure success.
See also
Casting Operators
Keywords
const_cast Operator
3/6/2021 • 2 minutes to read • Edit Online
Syntax
const_cast <type-id> (expression)
Remarks
A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is identical
except for the const , volatile , and __unaligned qualifiers. For pointers and references, the result will refer to
the original object. For pointers to data members, the result will refer to the same member as the original
(uncast) pointer to data member. Depending on the type of the referenced object, a write operation through the
resulting pointer, reference, or pointer to data member might produce undefined behavior.
You cannot use the const_cast operator to directly override a constant variable's constant status.
The const_cast operator converts a null pointer value to the null pointer value of the destination type.
Example
// expre_const_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>
int main() {
CCTest X;
X.setNumber( 8 );
X.printNumber();
}
On the line containing the const_cast , the data type of the this pointer is const CCTest * . The const_cast
operator changes the data type of the this pointer to CCTest * , allowing the member number to be modified.
The cast lasts only for the remainder of the statement in which it appears.
See also
Casting Operators
Keywords
reinterpret_cast Operator
3/6/2021 • 2 minutes to read • Edit Online
Allows any pointer to be converted into any other pointer type. Also allows any integral type to be converted
into any pointer type and vice versa.
Syntax
reinterpret_cast < type-id > ( expression )
Remarks
Misuse of the reinterpret_cast operator can easily be unsafe. Unless the desired conversion is inherently low-
level, you should use one of the other cast operators.
The reinterpret_castoperator can be used for conversions such as char* to int* , or One_class* to
Unrelated_class* , which are inherently unsafe.
The result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original
type. Other uses are, at best, nonportable.
The reinterpret_cast operator cannot cast away the const , volatile , or __unaligned attributes. See
const_cast Operator for information on removing these attributes.
The reinterpret_cast operator converts a null pointer value to the null pointer value of the destination type.
One practical use of reinterpret_cast is in a hash function, which maps a value to an index in such a way that
two distinct values rarely end up with the same index.
#include <iostream>
using namespace std;
Output:
64641
64645
64889
64893
64881
64885
64873
64877
64865
64869
64857
64861
64849
64853
64841
64845
64833
64837
64825
64829
The reinterpret_cast allows the pointer to be treated as an integral type. The result is then bit-shifted and
XORed with itself to produce a unique index (unique to a high degree of probability). The index is then truncated
by a standard C-style cast to the return type of the function.
See also
Casting Operators
Keywords
Run-Time Type Information
3/6/2021 • 2 minutes to read • Edit Online
Run-time type information (RTTI) is a mechanism that allows the type of an object to be determined during
program execution. RTTI was added to the C++ language because many vendors of class libraries were
implementing this functionality themselves. This caused incompatibilities between libraries. Thus, it became
obvious that support for run-time type information was needed at the language level.
For the sake of clarity, this discussion of RTTI is almost completely restricted to pointers. However, the concepts
discussed also apply to references.
There are three main C++ language elements to run-time type information:
The dynamic_cast operator.
Used for conversion of polymorphic types.
The typeid operator.
Used for identifying the exact type of an object.
The type_info class.
Used to hold the type information returned by the typeid operator.
See also
Casting
bad_typeid exception
3/6/2021 • 2 minutes to read • Edit Online
The bad_typeid exception is thrown by the typeid operator when the operand for typeid is a NULL pointer.
Syntax
catch (bad_typeid)
statement
Remarks
The interface for bad_typeid is:
The following example shows the typeid operator throwing a bad_typeid exception.
// expre_bad_typeid.cpp
// compile with: /EHsc /GR
#include <typeinfo>
#include <iostream>
class A{
public:
// object for class needs vtable
// for RTTI
virtual ~A();
};
try {
cout << typeid(*a).name() << endl; // Error condition
}
catch (bad_typeid){
cout << "Object is NULL" << endl;
}
}
Output
Object is NULL
See also
Run-Time Type Information
Keywords
type_info Class
3/6/2021 • 2 minutes to read • Edit Online
The type_info class describes type information generated within the program by the compiler. Objects of this
class effectively store a pointer to a name for the type. The type_info class also stores an encoded value
suitable for comparing two types for equality or collating order. The encoding rules and collating sequence for
types are unspecified and may differ between programs.
The <typeinfo> header file must be included in order to use the type_info class. The interface for the
type_info class is:
class type_info {
public:
type_info(const type_info& rhs) = delete; // cannot be copied
virtual ~type_info();
size_t hash_code() const;
_CRTIMP_PURE bool operator==(const type_info& rhs) const;
type_info& operator=(const type_info& rhs) = delete; // cannot be copied
_CRTIMP_PURE bool operator!=(const type_info& rhs) const;
_CRTIMP_PURE int before(const type_info& rhs) const;
size_t hash_code() const noexcept;
_CRTIMP_PURE const char* name() const;
_CRTIMP_PURE const char* raw_name() const;
};
You cannot instantiate objects of the type_info class directly, because the class has only a private copy
constructor. The only way to construct a (temporary) type_info object is to use the typeid operator. Since the
assignment operator is also private, you cannot copy or assign objects of class type_info .
type_info::hash_code defines a hash function suitable for mapping values of type typeinfo to a distribution of
index values.
The operators == and != can be used to compare for equality and inequality with other type_info objects,
respectively.
There is no link between the collating order of types and inheritance relationships. Use the type_info::before
member function to determine the collating sequence of types. There is no guarantee that type_info::before
will yield the same result in different programs or even different runs of the same program. In this manner,
type_info::before is similar to the address-of (&) operator.
The type_info::name member function returns a const char* to a null-terminated string representing the
human-readable name of the type. The memory pointed to is cached and should never be directly deallocated.
The type_info::raw_name member function returns a const char* to a null-terminated string representing the
decorated name of the object type. The name is actually stored in its decorated form to save space.
Consequently, this function is faster than type_info::name because it doesn't need to undecorate the name. The
string returned by the type_info::raw_name function is useful in comparison operations but is not readable. If
you need a human-readable string, use the type_info::name function instead.
Type information is generated for polymorphic classes only if the /GR (Enable Run-Time Type Information)
compiler option is specified.
See also
Run-Time Type Information
Statements (C++)
3/6/2021 • 2 minutes to read • Edit Online
C++ statements are the program elements that control how and in what order objects are manipulated. This
section includes:
Overview
Labeled Statements
Categories of Statements
Expression statements. These statements evaluate an expression for its side effects or for its return
value.
Null statements. These statements can be provided where a statement is required by the C++
syntax but where no action is to be taken.
Compound statements. These statements are groups of statements enclosed in curly braces ({ }).
They can be used wherever a single statement may be used.
Selection statements. These statements perform a test; they then execute one section of code if the
test evaluates to true (nonzero). They may execute another section of code if the test evaluates to
false.
Iteration statements. These statements provide for repeated execution of a block of code until a
specified termination criterion is met.
Jump statements. These statements either transfer control immediately to another location in the
function or return control from the function.
Declaration statements. Declarations introduce a name into a program.
For information on exception handling statements see Exception Handling.
See also
C++ Language Reference
Overview of C++ Statements
3/6/2021 • 2 minutes to read • Edit Online
C++ statements are executed sequentially, except when an expression statement, a selection statement, an
iteration statement, or a jump statement specifically modifies that sequence.
Statements may be of the following types:
labeled-statement
expression-statement
compound-statement
selection-statement
iteration-statement
jump-statement
declaration-statement
try-throw-catch
In most cases, the C++ statement syntax is identical to that of ANSI C89. The primary difference between the
two is that in C89, declarations are allowed only at the start of a block; C++ adds the declaration-statement ,
which effectively removes this restriction. This enables you to introduce variables at a point in the program
where a precomputed initialization value can be calculated.
Declaring variables inside blocks also allows you to exercise precise control over the scope and lifetime of those
variables.
The articles on statements describe the following C++ keywords:
break
case
catch
continue
default
do
else
__except
__finally
for
goto
if
__if_exists
__if_not_exists
__leave
return
switch
throw
__try
try
while
See also
Statements
Labeled Statements
3/6/2021 • 3 minutes to read • Edit Online
Labels are used to transfer program control directly to the specified statement.
identifier : statement
case constant-expression : statement
default : statement
Remarks
There are three types of labeled statements. All use a colon to separate some type of label from the statement.
The case and default labels are specific to case statements.
#include <iostream>
using namespace std;
void test_label(int x) {
if (x == 1){
goto label1;
}
goto label2;
label1:
cout << "in label1" << endl;
return;
label2:
cout << "in label2" << endl;
return;
}
int main() {
test_label(1); // in label1
test_label(2); // in label2
}
Test2:
cerr << "At Test2 label." << endl;
}
case WM_PAINT:
memset( &ps, 0x00, sizeof(PAINTSTRUCT) );
hDC = BeginPaint( hWnd, &ps );
EndPaint( hWnd, &ps );
break;
default:
// This choice is taken for all messages not specifically
// covered by a case statement.
case WM_PAINT:
// Obtain a handle to the device context.
// BeginPaint will send WM_ERASEBKGND if appropriate.
case WM_CLOSE:
// Close this window and all child windows.
default:
// This choice is taken for all messages not specifically
// covered by a case statement.
Test2:
cerr << "At Test2 label." << endl;
// At Test2 label.
}
See also
Overview of C++ Statements
switch Statement (C++)
Expression Statement
3/6/2021 • 2 minutes to read • Edit Online
Expression statements cause expressions to be evaluated. No transfer of control or iteration takes place as a
result of an expression statement.
The syntax for the expression statement is simply
Syntax
[expression ] ;
Remarks
All expressions in an expression statement are evaluated and all side effects are completed before the next
statement is executed. The most common expression statements are assignments and function calls. Since the
expression is optional, a semicolon alone is considered an empty expression statement, referred to as the null
statement.
See also
Overview of C++ Statements
Null Statement
3/6/2021 • 2 minutes to read • Edit Online
The "null statement" is an expression statement with the expression missing. It is useful when the syntax of the
language calls for a statement but no expression evaluation. It consists of a semicolon.
Null statements are commonly used as placeholders in iteration statements or as statements on which to place
labels at the end of compound statements or functions.
The following code fragment shows how to copy one string to another and incorporates the null statement:
// null_statement.cpp
char *myStrCpy( char *Dest, const char *Source )
{
char *DestStart = Dest;
return DestStart;
}
int main()
{
}
See also
Expression Statement
Compound Statements (Blocks)
3/6/2021 • 2 minutes to read • Edit Online
A compound statement consists of zero or more statements enclosed in curly braces ({ } ). A compound
statement can be used anywhere a statement is expected. Compound statements are commonly called "blocks."
Syntax
{ [ statement-list ] }
Remarks
The following example uses a compound statement as the statement part of the if statement (see The if
Statement for details about the syntax):
NOTE
Because a declaration is a statement, a declaration can be one of the statements in the statement-list. As a result, names
declared inside a compound statement, but not explicitly declared as static, have local scope and (for objects) lifetime. See
Scope for details about treatment of names with local scope.
See also
Overview of C++ Statements
Selection Statements (C++)
3/6/2021 • 2 minutes to read • Edit Online
The C++ selection statements, if and switch, provide a means to conditionally execute sections of code.
The __if_exists and __if_not_exists statements allow you to conditionally include code depending on the existence
of a symbol.
See the individual topics for the syntax for each statement.
See also
Overview of C++ Statements
if-else statement (C++)
11/2/2020 • 3 minutes to read • Edit Online
An if-else statement controls conditional branching. Statements in the if-branch are executed only if the
condition evaluates to a non-zero value (or true ). If the value of condition is nonzero, the following
statement gets executed, and the statement following the optional else gets skipped. Otherwise, the following
statement gets skipped, and if there's an else then the statement following the else gets executed.
condition expressions that evaluate to non-zero are:
true
a non-null pointer,
any non-zero arithmetic value, or
a class type that defines an unambiguous conversion to an arithmetic, boolean, or pointer type. (For
information about conversions, see Standard Conversions.)
Syntax
init-statement :
expression-statement
simple-declaration
condition :
expression
attribute-specifier-seq opt decl-specifier-seq declarator brace-or-equal-initializer
statement :
expression-statement
compound-statement
expression-statement :
expression opt ;
compound-statement :
{ statement-seq opt }
statement-seq :
statement
statement-seq statement
if-branch :
statement
else-branch :
statement
selection-statement :
if constexpr opt17 ( init-statement opt17 condition ) if-branch
if constexpr opt17 ( init-statement opt17 condition ) if-branch else else-branch
// if_else_statement.cpp
#include <iostream>
class C
{
public:
void do_something(){}
};
void init(C){}
bool is_true() { return true; }
int x = 10;
int main()
{
if (is_true())
{
cout << "b is true!\n"; // executed
}
else
{
cout << "b is false!\n";
}
// no else statement
if (x == 10)
{
x = 0;
}
C* c;
init(c);
if (c)
{
c->do_something();
}
else
{
cout << "c is null!\n";
}
}
#include <iostream>
#include <mutex>
#include <map>
#include <string>
#include <algorithm>
map<int, string> m;
mutex mx;
bool shared_flag; // guarded by mx
void unsafe_operation() {}
int main()
{
string s{ "if" };
if (auto keywords = { "if", "for", "while" }; any_of(keywords.begin(), keywords.end(), [&s](const char*
kw) { return s == kw; }))
{
cout << "Error! Token must not be a keyword\n";
}
}
if constexpr statements
Starting in C++17, you can use an if constexpr statement in function templates to make compile-time
branching decisions without having to resort to multiple function overloads. Microsoft-specific : This form is
available starting in Visual Studio 2017 version 15.3, and requires at least the /std:c++17 compiler option.
Example
This example shows how you can write a single function that handles parameter unpacking. No zero-parameter
overload is needed:
template <class T, class... Rest>
void f(T&& t, Rest&&... r)
{
// handle t
do_something(t);
// handle r conditionally
if constexpr (sizeof...(r))
{
f(r...);
}
else
{
g(r...);
}
}
See also
Selection Statements
Keywords
switch Statement (C++)
__if_exists Statement
3/6/2021 • 2 minutes to read • Edit Online
The __if_exists statement tests whether the specified identifier exists. If the identifier exists, the specified
statement block is executed.
Syntax
__if_exists ( identifier ) {
statements
};
Parameters
identifier
The identifier whose existence you want to test.
statements
One or more statements to execute if identifier exists.
Remarks
Cau t i on
To achieve the most reliable results, use the __if_exists statement under the following constraints.
Apply the __if_exists statement to only simple types, not templates.
Apply the __if_existsstatement to identifiers both inside or outside a class. Do not apply the
__if_exists statement to local variables.
Use the __if_existsstatement only in the body of a function. Outside of the body of a function, the
__if_exists statement can test only fully defined types.
When you test for overloaded functions, you cannot test for a specific form of the overload.
The complement to the __if_exists statement is the __if_not_exists statement.
Example
Notice that this example uses templates, which is not advised.
// the__if_exists_statement.cpp
// compile with: /EHsc
#include <iostream>
template<typename T>
class X : public T {
public:
void Dump() {
std::cout << "In X<T>::Dump()" << std::endl;
__if_exists(T::Dump) {
T::Dump();
}
__if_not_exists(T::Dump) {
std::cout << "T::Dump does not exist" << std::endl;
}
}
};
class A {
public:
void Dump() {
std::cout << "In A::Dump()" << std::endl;
}
};
class B {};
class C {
public:
void f(int);
void f(double);
};
int main() {
X<A> x1;
X<B> x2;
x1.Dump();
x2.Dump();
__if_exists(::g_bFlag) {
std::cout << "g_bFlag = " << g_bFlag << std::endl;
}
__if_exists(C::f) {
std::cout << "C::f exists" << std::endl;
}
return 0;
}
Output
In X<T>::Dump()
In A::Dump()
In X<T>::Dump()
T::Dump does not exist
g_bFlag = 1
C::f exists
See also
Selection Statements
Keywords
__if_not_exists Statement
__if_not_exists Statement
3/6/2021 • 2 minutes to read • Edit Online
The __if_not_exists statement tests whether the specified identifier exists. If the identifier does not exist, the
specified statement block is executed.
Syntax
__if_not_exists ( identifier ) {
statements
};
Parameters
identifier
The identifier whose existence you want to test.
statements
One or more statements to execute if identifier does not exist.
Remarks
Cau t i on
To achieve the most reliable results, use the __if_not_exists statement under the following constraints.
Apply the __if_not_exists statement to only simple types, not templates.
Apply the __if_not_existsstatement to identifiers both inside or outside a class. Do not apply the
__if_not_exists statement to local variables.
Use the __if_not_existsstatement only in the body of a function. Outside of the body of a function, the
__if_not_exists statement can test only fully defined types.
When you test for overloaded functions, you cannot test for a specific form of the overload.
The complement to the __if_not_exists statement is the __if_exists statement.
Example
For an example about how to use __if_not_exists , see __if_exists Statement.
See also
Selection Statements
Keywords
__if_exists Statement
switch statement (C++)
11/2/2020 • 4 minutes to read • Edit Online
Allows selection among multiple sections of code, depending on the value of an integral expression.
Syntax
selection-statement :
switch ( init-statement optC++17 condition ) statement
init-statement :
expression-statement
simple-declaration
condition :
expression
attribute-specifier-seq opt decl-specifier-seq declarator brace-or-equal-initializer
labeled-statement :
case constant-expression : statement
default : statement
Remarks
A switch statement causes control to transfer to one labeled-statement in its statement body, depending on
the value of condition .
The condition must have an integral type, or be a class type that has an unambiguous conversion to integral
type. Integral promotion takes place as described in Standard conversions.
The switch statement body consists of a series of case labels and an optional default label. A
labeled-statement is one of these labels and the statements that follow. The labeled statements aren't syntactic
requirements, but the switch statement is meaningless without them. No two constant-expression values in
case statements may evaluate to the same value. The default label may appear only once. The default
statement is often placed at the end, but it can appear anywhere in the switch statement body. A case or
default label can only appear inside a switch statement.
The constant-expression in each case label is converted to a constant value that's the same type as condition .
Then, it's compared with condition for equality. Control passes to the first statement after the case
constant-expression value that matches the value of condition . The resulting behavior is shown in the
following table.
switch statement behavior
C O N DIT IO N A C T IO N
Converted value matches that of the promoted controlling Control is transferred to the statement following that label.
expression.
C O N DIT IO N A C T IO N
None of the constants match the constants in the case Control is transferred to the default label.
labels; a default label is present.
None of the constants match the constants in the case Control is transferred to the statement after the switch
labels; no default label is present. statement.
If a matching expression is found, execution can continue through later case or default labels. The break
statement is used to stop execution and transfer control to the statement after the switch statement. Without a
break statement, every statement from the matched case label to the end of the switch , including the
default , is executed. For example:
// switch_statement1.cpp
#include <stdio.h>
int main() {
const char *buffer = "Any character stream";
int uppercase_A, lowercase_a, other;
char c;
uppercase_A = lowercase_a = other = 0;
In the above example, uppercase_A is incremented if c is an uppercase 'A' . The break statement after
uppercase_A++ terminates execution of the switch statement body and control passes to the while loop.
Without the break statement, execution would "fall through" to the next labeled statement, so that lowercase_a
and other would also be incremented. A similar purpose is served by the break statement for case 'a' . If c
is a lowercase 'a' , lowercase_a is incremented and the break statement terminates the switch statement
body. If c isn't an 'a' or 'A' , the default statement is executed.
Visual Studio 2017 and later : (available with /std:c++17) The [[fallthrough]] attribute is specified in the
C++17 standard. You can use it in a switch statement. It's a hint to the compiler, or anyone who reads the code,
that fall-through behavior is intentional. The Microsoft C++ compiler currently doesn't warn on fallthrough
behavior, so this attribute has no effect on compiler behavior. In the example, the attribute gets applied to an
empty statement within the unterminated labeled statement. In other words, the semicolon is necessary.
int main()
{
int n = 5;
switch (n)
{
case 1:
a();
break;
case 2:
b();
d();
[[fallthrough]]; // I meant to do this!
case 3:
c();
break;
default:
d();
break;
}
return 0;
}
Visual Studio 2017 version 15.3 and later (available with /std:c++17). A switch statement may have an
init-statement clause, which ends with a semicolon. It introduces and initializes a variable whose scope is
limited to the block of the switch statement:
An inner block of a switch statement can contain definitions with initializers as long as they're reachable, that
is, not bypassed by all possible execution paths. Names introduced using these declarations have local scope.
For example:
// switch_statement2.cpp
// C2360 expected
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
switch( tolower( *argv[1] ) )
{
// Error. Unreachable declaration.
char szChEntered[] = "Character entered was: ";
case 'a' :
{
// Declaration of szChEntered OK. Local scope.
char szChEntered[] = "Character entered was: ";
cout << szChEntered << "a\n";
}
break;
case 'b' :
// Value of szChEntered undefined.
cout << szChEntered << "b\n";
break;
default:
// Value of szChEntered undefined.
cout << szChEntered << "neither a nor b\n";
break;
}
}
A switch statement can be nested. When nested, the case or default labels associate with the closest switch
statement that encloses them.
Microsoft-specific behavior
Microsoft C++ doesn't limit the number of case values in a switch statement. The number is limited only by
the available memory.
See also
Selection Statements
Keywords
Iteration Statements (C++)
3/6/2021 • 2 minutes to read • Edit Online
Iteration statements cause statements (or compound statements) to be executed zero or more times, subject to
some loop-termination criteria. When these statements are compound statements, they are executed in order,
except when either the break statement or the continue statement is encountered.
C++ provides four iteration statements — while, do, for, and range-based for. Each of these iterates until its
termination expression evaluates to zero (false), or until loop termination is forced with a break statement. The
following table summarizes these statements and their actions; each is discussed in detail in the sections that
follow.
Iteration Statements
STAT EM EN T EVA L UAT ED AT IN IT IA L IZ AT IO N IN C REM EN T
do Bottom of loop No No
The statement part of an iteration statement cannot be a declaration. However, it can be a compound statement
containing a declaration.
See also
Overview of C++ Statements
while Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
while ( expression )
statement
Remarks
The test of expression takes place before each execution of the loop; therefore, a while loop executes zero or
more times. expression must be of an integral type, a pointer type, or a class type with an unambiguous
conversion to an integral or pointer type.
A while loop can also terminate when a break, goto, or return within the statement body is executed. Use
continue to terminate the current iteration without exiting the while loop. continue passes control to the next
iteration of the while loop.
The following code uses a while loop to trim trailing underscores from a string:
// while_statement.cpp
#include <string.h>
#include <stdio.h>
char *trim( char *szSource )
{
char *pszEOS = 0;
return szSource;
}
int main()
{
char szbuf[] = "12345_____";
The termination condition is evaluated at the top of the loop. If there are no trailing underscores, the loop never
executes.
See also
Iteration Statements
Keywords
do-while Statement (C++)
for Statement (C++)
Range-based for Statement (C++)
do-while Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
Executes a statement repeatedly until the specified termination condition (the expression) evaluates to zero.
Syntax
do
statement
while ( expression ) ;
Remarks
The test of the termination condition is made after each execution of the loop; therefore, a do-while loop
executes one or more times, depending on the value of the termination expression. The do-while statement can
also terminate when a break, goto, or return statement is executed within the statement body.
The expression must have arithmetic or pointer type. Execution proceeds as follows:
1. The statement body is executed.
2. Next, expression is evaluated. If expression is false, the do-while statement terminates and control
passes to the next statement in the program. If expression is true (nonzero), the process is repeated,
beginning with step 1.
Example
The following sample demonstrates the do-while statement:
// do_while_statement.cpp
#include <stdio.h>
int main()
{
int i = 0;
do
{
printf_s("\n%d",i++);
} while (i < 3);
}
See also
Iteration Statements
Keywords
while Statement (C++)
for Statement (C++)
Range-based for Statement (C++)
for statement (C++)
11/2/2020 • 3 minutes to read • Edit Online
Executes a statement repeatedly until the condition becomes false. For information on the range-based for
statement, see Range-based for statement (C++).
Syntax
for ( init-expression ; cond-expression ; loop-expression )
statement
Remarks
Use the for statement to construct loops that must execute a specified number of times.
The for statement consists of three optional parts, as shown in the following table.
for loop elements
SY N TA X N A M E W H EN EXEC UT ED DESC RIP T IO N
init-expression Before any other element of the for Often used to initialize loop indices. It
statement, init-expression is can contain expressions or
executed only once. Control then declarations.
passes to cond-expression .
The following examples show different ways to use the for statement.
#include <iostream>
using namespace std;
int main() {
// The counter variable can be declared in the init-expression.
for (int i = 0; i < 2; i++ ){
cout << i;
}
// Output: 01
// The counter variable can be declared outside the for loop.
int i;
for (i = 0; i < 2; i++){
cout << i;
}
// Output: 01
// These for loops are the equivalent of a while loop.
i = 0;
while (i < 2){
cout << i++;
}
// Output: 01
}
init-expression and loop-expression can contain multiple statements separated by commas. For example:
#include <iostream>
using namespace std;
int main(){
int i, j;
for ( i = 5, j = 10 ; i + j < 20; i++, j++ ) {
cout << "i + j = " << (i + j) << '\n';
}
}
// Output:
i + j = 15
i + j = 17
i + j = 19
#include <iostream>
using namespace std;
int main(){
for (int i = 10; i > 0; i--) {
cout << i << ' ';
}
// Output: 10 9 8 7 6 5 4 3 2 1
for (int i = 10; i < 20; i = i+2) {
cout << i << ' ';
}
// Output: 10 12 14 16 18
A loop terminates when a break , return, or goto (to a labeled statement outside the for loop) within
for
statement is executed. A continue statement in a for loop terminates only the current iteration.
If cond-expression is omitted, it's considered true , and the for loop won't terminate without a break ,
return , or goto within statement .
Although the three fields of the for statement are normally used for initialization, testing for termination, and
incrementing, they're not restricted to these uses. For example, the following code prints the numbers 0 through
4. In this case, statement is the null statement:
#include <iostream>
using namespace std;
int main()
{
int i;
for( i = 0; i < 5; cout << i << '\n', i++){
;
}
}
By default, under /Ze, a variable declared in a for loop remains in scope until the for loop's enclosing scope
ends.
/Zc:forScope enables standard behavior of variables declared in for loops without needing to specify /Za .
It's also possible to use the scoping differences of the for loop to redeclare variables under /Ze as follows:
// for_statement5.cpp
int main(){
int i = 0; // hidden by var with same name declared in for loop
for ( int i = 0 ; i < 3; i++ ) {}
This behavior more closely mimics the standard behavior of a variable declared in a for loop, which requires
variables declared in a for loop to go out of scope after the loop is done. When a variable is declared in a for
loop, the compiler internally promotes it to a local variable in the for loop's enclosing scope. It's promoted
even if there's already a local variable with the same name.
See also
Iteration statements
Keywords
while statement (C++)
do-while statement (C++)
Range-based for statement (C++)
Range-based for Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
for ( for-range-declaration : expression )
statement
Remarks
Use the range-based for statement to construct loops that must execute through a range, which is defined as
anything that you can iterate through—for example, std::vector , or any other C++ Standard Library sequence
whose range is defined by a begin() and end() . The name that is declared in the for-range-declaration
portion is local to the for statement and cannot be re-declared in expression or statement . Note that the
auto keyword is preferred in the for-range-declaration portion of the statement.
New in Visual Studio 2017: Range-based for loops no longer require that begin() and end() return
objects of the same type. This enables end() to return a sentinel object such as used by ranges as defined in the
Ranges-V3 proposal. For more information, see Generalizing the Range-Based For Loop and the range-v3
library on GitHub.
This code shows how to use range-based for loops to iterate through an array and a vector:
// range-based-for.cpp
// compile by using: cl /EHsc /nologo /W4
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// Basic 10-element integer array.
int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
end of integer array test
0.14159 1.14159 2.14159 3.14159 4.14159 5.14159 6.14159 7.14159 8.14159 9.14159
end of vector test
A range-based for loop terminates when one of these in statement is executed: a break , return , or goto to
a labeled statement outside the range-based for loop. A continue statement in a range-based for loop
terminates only the current iteration.
Keep in mind these facts about range-based for :
Automatically recognizes arrays.
Recognizes containers that have .begin() and .end() .
Uses argument-dependent lookup begin() and end() for anything else.
See also
auto
Iteration Statements
Keywords
while Statement (C++)
do-while Statement (C++)
for Statement (C++)
Jump Statements (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
break;
continue;
return [expression];
goto identifier;
Remarks
See the following topics for a description of the C++ jump statements.
break Statement
continue Statement
return Statement
goto Statement
See also
Overview of C++ Statements
break Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
The break statement ends execution of the nearest enclosing loop or conditional statement in which it appears.
Control passes to the statement that follows the end of the statement, if any.
Syntax
break;
Remarks
The break statement is used with the conditional switch statement and with the do, for, and while loop
statements.
In a switch statement, the break statement causes the program to execute the next statement outside the
switch statement. Without a break statement, every statement from the matched case label to the end of the
switch statement, including the default clause, is executed.
In loops, the break statement ends execution of the nearest enclosing do , for , or while statement. Control
passes to the statement that follows the ended statement, if any.
Within nested statements, the break statement ends only the do , for , switch , or while statement that
immediately encloses it. You can use a return or goto statement to transfer control from more deeply nested
structures.
Example
The following code shows how to use the break statement in a for loop.
#include <iostream>
using namespace std;
int main()
{
// An example of a standard for loop
for (int i = 1; i < 10; i++)
{
if (i == 4) {
break;
}
cout << i << '\n';
}
In each case:
1
2
3
The following code shows how to use break in a while loop and a do loop.
#include <iostream>
using namespace std;
int main() {
int i = 0;
i = 0;
do {
if (i == 4) {
break;
}
cout << i << '\n';
i++;
} while (i < 10);
}
In each case:
0123
The following code shows how to use break in a switch statement. You must use break in every case if you
want to handle each case separately; if you do not use break , the code execution falls through to the next case.
#include <iostream>
using namespace std;
int main() {
Suit hand;
. . .
// Assume that some enum value is set for hand
// In this example, each case is handled separately
switch (hand)
{
case Diamonds:
cout << "got Diamonds \n";
break;
case Hearts:
cout << "got Hearts \n";
break;
case Clubs:
cout << "got Clubs \n";
break;
case Spades:
cout << "got Spades \n";
break;
default:
cout << "didn't get card \n";
}
// In this example, Diamonds and Hearts are handled one way, and
// Clubs, Spades, and the default value are handled another way
switch (hand)
{
case Diamonds:
case Hearts:
cout << "got a red card \n";
break;
case Clubs:
case Spades:
default:
cout << "didn't get a red card \n";
}
}
See also
Jump Statements
Keywords
continue Statement
continue Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
Forces transfer of control to the controlling expression of the smallest enclosing do, for, or while loop.
Syntax
continue;
Remarks
Any remaining statements in the current iteration are not executed. The next iteration of the loop is determined
as follows:
In a do or while loop, the next iteration starts by reevaluating the controlling expression of the do or
while statement.
In a for loop (using the syntax for( <init-expr> ; <cond-expr> ; <loop-expr> ) ), the <loop-expr>
clause is executed. Then the <cond-expr> clause is reevaluated and, depending on the result, the loop
either ends or another iteration occurs.
The following example shows how the continue statement can be used to bypass sections of code and begin
the next iteration of a loop.
Example
// continue_statement.cpp
#include <stdio.h>
int main()
{
int i = 0;
do
{
i++;
printf_s("before the continue\n");
continue;
printf("after the continue, should never print\n");
} while (i < 3);
See also
Jump Statements
Keywords
return Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
Terminates the execution of a function and returns control to the calling function (or to the operating system if
you transfer control from the main function). Execution resumes in the calling function at the point immediately
following the call.
Syntax
return [expression];
Remarks
The expression clause, if present, is converted to the type specified in the function declaration, as if an
initialization were being performed. Conversion from the type of the expression to the return type of the
function can create temporary objects. For more information about how and when temporaries are created, see
Temporary Objects.
The value of the expression clause is returned to the calling function. If the expression is omitted, the return
value of the function is undefined. Constructors and destructors, and functions of type void ,cannot specify an
expression in the return statement. Functions of all other types must specify an expression in the return
statement.
When the flow of control exits the block enclosing the function definition, the result is the same as it would be if
a return statement without an expression had been executed. This is invalid for functions that are declared as
returning a value.
A function can have any number of return statements.
The following example uses an expression with a return statement to obtain the largest of two integers.
Example
// return_statement2.cpp
#include <stdio.h>
int main()
{
int nOne = 5;
int nTwo = 7;
See also
Jump Statements
Keywords
goto Statement (C++)
3/6/2021 • 2 minutes to read • Edit Online
The goto statement unconditionally transfers control to the statement labeled by the specified identifier.
Syntax
goto identifier;
Remarks
The labeled statement designated by identifier must be in the current function. All identifier names are
members of an internal namespace and therefore do not interfere with other identifiers.
A statement label is meaningful only to a goto statement; otherwise, statement labels are ignored. Labels
cannot be redeclared.
A goto statement is not allowed to transfer control to a location that skips over the initialization of any variable
that is in scope in that location. The following example raises C2362:
int goto_fn(bool b)
{
if (!b)
{
goto exit; // C2362
}
else
{ /*...*/ }
exit:
return error_code;
}
It is good programming style to use the break , continue , and return statements instead of the goto
statement whenever possible. However, because the break statement exits from only one level of a loop, you
might have to use a goto statement to exit a deeply nested loop.
For more information about labels and the goto statement, see Labeled Statements.
Example
In this example, a goto statement transfers control to the point labeled stop when i equals 3.
// goto_statement.cpp
#include <stdio.h>
int main()
{
int i, j;
stop:
printf_s( "Jumped to stop. i = %d\n", i );
}
See also
Jump Statements
Keywords
Transfers of Control
3/6/2021 • 2 minutes to read • Edit Online
You can use the goto statement or a case label in a switch statement to specify a program that branches past
an initializer. Such code is illegal unless the declaration that contains the initializer is in a block enclosed by the
block in which the jump statement occurs.
The following example shows a loop that declares and initializes the objects total , ch , and i . There is also an
erroneous goto statement that transfers control past an initializer.
// transfers_of_control.cpp
// compile with: /W1
// Read input until a nonnumeric character is entered.
int main()
{
char MyArray[5] = {'2','2','a','c'};
int i = 0;
while( 1 )
{
int total = 0;
char ch = MyArray[i++];
int i = ch - '0';
Label1:
total += i; // C4700: transfers past initialization of i.
} // i would be destroyed here if goto error were not present
else
// Break statement transfers control out of loop,
// destroying total and ch.
break;
}
}
In the preceding example, the goto statement tries to transfer control past the initialization of i . However, if
i were declared but not initialized, the transfer would be legal.
The objects total and ch , declared in the block that serves as the statement of the while statement, are
destroyed when that block is exited using the break statement.
Namespaces (C++)
3/6/2021 • 7 minutes to read • Edit Online
A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions,
variables, etc) inside it. Namespaces are used to organize code into logical groups and to prevent name
collisions that can occur especially when your code base includes multiple libraries. All identifiers at namespace
scope are visible to one another without qualification. Identifiers outside the namespace can access the
members by using the fully qualified name for each identifier, for example std::vector<std::string> vec; , or
else by a using Declaration for a single identifier ( using std::string ), or a using Directive for all the identifiers
in the namespace ( using namespace std; ). Code in header files should always use the fully qualified namespace
name.
The following example shows a namespace declaration and three ways that code outside the namespace can
accesses their members.
namespace ContosoData
{
class ObjectManager
{
public:
void DoSomething() {}
};
void Func(ObjectManager) {}
}
ContosoData::ObjectManager mgr;
mgr.DoSomething();
ContosoData::Func(mgr);
using ContosoData::ObjectManager;
ObjectManager mgr;
mgr.DoSomething();
ObjectManager mgr;
mgr.DoSomething();
Func(mgr);
using directives
The using directive allows all the names in a namespace to be used without the namespace-name as an explicit
qualifier. Use a using directive in an implementation file (i.e. *.cpp) if you are using several different identifiers in
a namespace; if you are just using one or two identifiers, then consider a using declaration to only bring those
identifiers into scope and not all the identifiers in the namespace. If a local variable has the same name as a
namespace variable, the namespace variable is hidden. It is an error to have a namespace variable with the same
name as a global variable.
NOTE
A using directive can be placed at the top of a .cpp file (at file scope), or inside a class or function definition.
In general, avoid putting using directives in header files (*.h) because any file that includes that header will bring
everything in the namespace into scope, which can cause name hiding and name collision problems that are very difficult
to debug. Always use fully qualified names in a header file. If those names get too long, you can use a namespace alias to
shorten them. (See below.)
//contosoData.h
#pragma once
namespace ContosoDataServer
{
void Foo();
int Bar();
}
Function implementations in contosodata.cpp should use the fully qualified name, even if you place a using
directive at the top of the file:
#include "contosodata.h"
using namespace ContosoDataServer;
A namespace can be declared in multiple blocks in a single file, and in multiple files. The compiler joins the parts
together during preprocessing and the resulting namespace contains all the members declared in all the parts.
An example of this is the std namespace which is declared in each of the header files in the standard library.
Members of a named namespace can be defined outside the namespace in which they are declared by explicit
qualification of the name being defined. However, the definition must appear after the point of declaration in a
namespace that encloses the declaration's namespace. For example:
// defining_namespace_members.cpp
// C2039 expected
namespace V {
void f();
}
void V::f() { } // ok
void V::g() { } // C2039, g() is not yet a member of V
namespace V {
void g();
}
This error can occur when namespace members are declared across multiple header files, and you have not
included those headers in the correct order.
Nested namespaces
Namespaces may be nested. An ordinary nested namespace has unqualified access to its parent's members, but
the parent members do not have unqualified access to the nested namespace (unless it is declared as inline), as
shown in the following example:
namespace ContosoDataServer
{
void Foo();
namespace Details
{
int CountImpl;
void Ban() { return Foo(); }
}
int Bar(){...};
int Baz(int i) { return Details::CountImpl; }
}
Ordinary nested namespaces can be used to encapsulate internal implementation details that are not part of the
public interface of the parent namespace.
//Header.h
#include <string>
namespace Test
{
namespace old_ns
{
std::string Func() { return std::string("Hello from old"); }
}
#include "header.h"
#include <string>
#include <iostream>
int main()
{
using namespace Test;
using namespace std;
string s = Func();
std::cout << s << std::endl; // "Hello from new"
return 0;
}
The following example shows how you can declare a specialization in a parent of a template that is declared in
an inline namespace:
namespace Parent
{
inline namespace new_ns
{
template <typename T>
struct C
{
T member;
};
}
template<>
class C<int> {};
}
You can use inline namespaces as a versioning mechanism to manage changes to the public interface of a
library. For example, you can create a single parent namespace, and encapsulate each version of the interface in
its own namespace nested inside the parent. The namespace that holds the most recent or preferred version is
qualified as inline, and is therefore exposed as if it were a direct member of the parent namespace. Client code
that invokes the Parent::Class will automatically bind to the new code. Clients that prefer to use the older version
can still access it by using the fully qualified path to the nested namespace that has that code.
The inline keyword must be applied to the first declaration of the namespace in a compilation unit.
The following example shows two versions of an interface, each in a nested namespace. The v_20 namespace
has some modification from the v_10 interface and is marked as inline. Client code that uses the new library
and calls Contoso::Funcs::Add will invoke the v_20 version. Code that attempts to call Contoso::Funcs::Divide
will now get a compile time error. If they really need that function, they can still access the v_10 version by
explicitly calling Contoso::v_10::Funcs::Divide .
namespace Contoso
{
namespace v_10
{
template <typename T>
class Funcs
{
public:
Funcs(void);
T Add(T a, T b);
T Subtract(T a, T b);
T Multiply(T a, T b);
T Divide(T a, T b);
};
}
Namespace aliases
Namespace names need to be unique, which means that often they should not be too short. If the length of a
name makes code difficult to read, or is tedious to type in a header file where using directives can't be used, then
you can make a namespace alias which serves as an abbreviation for the actual name. For example:
namespace
{
int MyFunc(){}
}
This is called an unnamed or anonymous namespace and it is useful when you want to make variable
declarations invisible to code in other files (i.e. give them internal linkage) without having to create a named
namespace. All code in the same file can see the identifiers in an unnamed namespace but the identifiers, along
with the namespace itself, are not visible outside that file—or more precisely outside the translation unit.
See also
Declarations and Definitions
Enumerations (C++)
3/6/2021 • 5 minutes to read • Edit Online
An enumeration is a user-defined type that consists of a set of named integral constants that are known as
enumerators.
NOTE
This article covers the ISO Standard C++ Language enum type and the scoped (or strongly-typed) enum class type
which is introduced in C++11. For information about the public enum class or private enum class types in C++/CLI
and C++/CX, see enum class.
Syntax
// unscoped enum:
enum [identifier] [: type]
{enum-list};
// scoped enum:
enum [class|struct]
[identifier] [: type]
{enum-list};
Parameters
identifier
The type name given to the enumeration.
type
The underlying type of the enumerators; all enumerators have the same underlying type. May be any integral
type.
enum-list
Comma-separated list of the enumerators in the enumeration. Every enumerator or variable name in the scope
must be unique. However, the values can be duplicated. In a unscoped enum, the scope is the surrounding scope;
in a scoped enum, the scope is the enum-list itself. In a scoped enum, the list may be empty which in effect
defines a new integral type.
class
By using this keyword in the declaration, you specify the enum is scoped, and an identifier must be provided.
You can also use the struct keyword in place of class , as they are semantically equivalent in this context.
Enumerator scope
An enumeration provides context to describe a range of values which are represented as named constants and
are also called enumerators. In the original C and C++ enum types, the unqualified enumerators are visible
throughout the scope in which the enum is declared. In scoped enums, the enumerator name must be qualified
by the enum type name. The following example demonstrates this basic difference between the two kinds of
enums:
namespace CardGame_Scoped
{
enum class Suit { Diamonds, Hearts, Clubs, Spades };
namespace CardGame_NonScoped
{
enum Suit { Diamonds, Hearts, Clubs, Spades };
Every name in an enumeration is assigned an integral value that corresponds to its place in the order of the
values in the enumeration. By default, the first value is assigned 0, the next one is assigned 1, and so on, but you
can explicitly set the value of an enumerator, as shown here:
The enumerator Diamonds is assigned the value 1 . Subsequent enumerators, if they are not given an explicit
value, receive the value of the previous enumerator plus one. In the previous example, Hearts would have the
value 2, Clubs would have 3, and so on.
Every enumerator is treated as a constant and must have a unique name within the scope where the enum is
defined (for unscoped enums) or within the enum itself (for scoped enums). The values given to the names do
not have to be unique. For example, if the declaration of a unscoped enum Suit is this:
Then the values of Diamonds , Hearts , Clubs , and Spades are 5, 6, 4, and 5, respectively. Notice that 5 is used
more than once; this is allowed even though it may not be intended. These rules are the same for scoped enums.
Casting rules
Unscoped enum constants can be implicitly converted to int , but an int is never implicitly convertible to an
enum value. The following example shows what happens if you try to assign hand a value that is not a Suit :
Using implicit conversions in this way can lead to unintended side-effects. To help eliminate programming
errors associated with unscoped enums, scoped enum values are strongly typed. Scoped enumerators must be
qualified by the enum type name (identifier) and cannot be implicitly converted, as shown in the following
example:
namespace ScopedEnumConversions
{
enum class Suit { Diamonds, Hearts, Clubs, Spades };
void AttemptConversions()
{
Suit hand;
hand = Clubs; // error C2065: 'Clubs' : undeclared identifier
hand = Suit::Clubs; //Correct.
int account_num = 135692;
hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'
hand = static_cast<Suit>(account_num); // OK, but probably a bug!!!
account_num = Suit::Hearts; // error C2440: '=' : cannot convert from 'Suit' to 'int'
account_num = static_cast<int>(Suit::Hearts); // OK
}
}
Notice that the line hand = account_num; still causes the error that occurs with unscoped enums, as shown
earlier. It is allowed with an explicit cast. However, with scoped enums, the attempted conversion in the next
statement, account_num = Suit::Hearts; , is no longer allowed without an explicit cast.
The new type is an exact copy of the underlying type, and therefore has the same calling convention, which
means it can be used across ABIs without any performance penalty. No cast is required when variables of the
type are initialized by using direct-list initialization. The following example shows how to initialize enums with
no enumerators in various contexts:
enum class byte : unsigned char { };
struct X
{
E e{ 0 };
X() : e{ 0 } { }
};
E* p = new E{ 0 };
int main()
{
f(E{ 0 });
byte i{ 42 };
byte j = byte{ 42 };
// unsigned char c = j; // C2440: 'initializing': cannot convert from 'byte' to 'unsigned char'
return 0;
}
See also
C Enumeration Declarations
Keywords
union
11/2/2020 • 8 minutes to read • Edit Online
NOTE
In C++17 and later, the std::variant class is a type-safe alternative for a union.
A union is a user-defined type in which all members share the same memory location. This definition means
that at any given time, a union can contain no more than one object from its list of members. It also means that
no matter how many members a union has, it always uses only enough memory to store the largest member.
A union can be useful for conserving memory when you have lots of objects and limited memory. However, a
union requires extra care to use correctly. You're responsible for ensuring that you always access the same
member you assigned. If any member types have a non-trivial constructor, then you must write additional code
to explicitly construct and destroy that member. Before you use a union, consider whether the problem you're
trying to solve could be better expressed by using a base class and derived class types.
Syntax
union tag opt { member-list };
Parameters
tag
The type name given to the union.
member-list
Members that the union can contain.
Declare a union
Begin the declaration of a union by using the union keyword, and enclose the member list in curly braces:
// declaring_a_union.cpp
union RecordType // Declare a simple union type
{
char ch;
int i;
long l;
float f;
double d;
int *int_ptr;
};
int main()
{
RecordType t;
t.i = 5; // t holds an int
t.f = 7.25; // t now holds a float
}
Use a union
In the previous example, any code that accesses the union needs to know which member holds the data. The
most common solution to this problem is called a discriminated union. It encloses the union in a struct, and
includes an enum member that indicates the member type currently stored in the union. The following example
shows the basic pattern:
#include <queue>
struct TempData
{
int StationId;
time_t time;
double current;
double max;
double min;
};
struct WindData
{
int StationId;
time_t time;
int speed;
short direction;
};
struct Input
{
WeatherDataType type;
union
{
TempData temp;
WindData wind;
};
};
Input second;
second.type = WeatherDataType::Wind;
second.wind = { 204, 1418859354, 14, 27 };
inputs.push(second);
}
}
return 0;
}
In the previous example, the union in the Input struct has no name, so it's called an anonymous union. Its
members can be accessed directly as if they're members of the struct. For more information about how to use
an anonymous union, see the Anonymous union section.
The previous example shows a problem that you could also solve by using class types that derive from a
common base class. You could branch your code based on the runtime type of each object in the container. Your
code might be easier to maintain and understand, but it might also be slower than using a union. Also, with a
union, you can store unrelated types. A union lets you dynamically change the type of the stored value without
changing the type of the union variable itself. For example, you could create a heterogeneous array of
MyUnionType , whose elements store different values of different types.
It's easy to misuse the Input struct in the example. It's up to the user to use the discriminator correctly to access
the member that holds the data. You can protect against misuse by making the union private and providing
special access functions, as shown in the next example.
// for MyVariant
#include <crtdbg.h>
#include <new>
#include <utility>
struct A
{
A() = default;
A(int i, const string& str) : num(i), name(str) {}
int num;
int num;
string name;
//...
};
struct B
{
B() = default;
B(int i, const string& str) : num(i), name(str) {}
int num;
string name;
vector<int> vec;
// ...
};
MyVariant(Kind kind)
: kind_(kind)
{
switch (kind_)
{
case Kind::None:
break;
case Kind::A:
new (&a_) A();
break;
case Kind::B:
new (&b_) B();
break;
case Kind::Integer:
i_ = 0;
break;
default:
_ASSERT(false);
break;
}
}
~MyVariant()
{
switch (kind_)
{
case Kind::None:
break;
case Kind::A:
a_.~A();
break;
case Kind::B:
b_.~B();
break;
case Kind::Integer:
break;
default:
_ASSERT(false);
break;
}
kind_ = Kind::None;
}
MyVariant(MyVariant&& other)
: kind_(other.kind_)
{
switch (kind_)
{
case Kind::None:
break;
case Kind::A:
new (&a_) A(move(other.a_));
break;
case Kind::B:
new (&b_) B(move(other.b_));
break;
case Kind::Integer:
i_ = other.i_;
break;
default:
_ASSERT(false);
break;
}
other.kind_ = Kind::None;
}
MyVariant(const A& a)
: kind_(Kind::A), a_(a)
{
}
MyVariant(A&& a)
: kind_(Kind::A), a_(move(a))
{
}
MyVariant& operator=(A&& a)
{
if (kind_ != Kind::A)
{
this->~MyVariant();
new (this) MyVariant(move(a));
}
else
{
a_ = move(a);
}
return *this;
}
MyVariant(const B& b)
: kind_(Kind::B), b_(b)
: kind_(Kind::B), b_(b)
{
}
MyVariant(B&& b)
: kind_(Kind::B), b_(move(b))
{
}
MyVariant& operator=(B&& b)
{
if (kind_ != Kind::B)
{
this->~MyVariant();
new (this) MyVariant(move(b));
}
else
{
b_ = move(b);
}
return *this;
}
MyVariant(int i)
: kind_(Kind::Integer), i_(i)
{
}
MyVariant& operator=(int i)
{
if (kind_ != Kind::Integer)
{
this->~MyVariant();
new (this) MyVariant(i);
}
else
{
i_ = i;
}
return *this;
}
A& GetA()
{
_ASSERT(kind_ == Kind::A);
return a_;
}
B& GetB()
{
_ASSERT(kind_ == Kind::B);
return b_;
}
int& GetInteger()
{
_ASSERT(kind_ == Kind::Integer);
return i_;
}
private:
Kind kind_;
union
{
A a_;
B b_;
int i_;
};
};
#pragma warning (pop)
int main()
{
A a(1, "Hello from A");
B b(2, "Hello from B");
MyVariant mv_1 = a;
b.vec = { 10,20,30,40,50 };
mv_1 = move(b);
cout << "After move, mv_1 = b: vec.size = " << mv_1.GetB().vec.size() << endl;
A union can't store a reference. A union also doesn’t support inheritance. That means you can't use a union as a
base class, or inherit from another class, or have virtual functions.
Initialize a union
You can declare and initialize a union in the same statement by assigning an expression enclosed in braces. The
expression is evaluated and assigned to the first field of the union.
#include <iostream>
using namespace std;
union NumericType
{
short iValue;
long lValue;
double dValue;
};
int main()
{
union NumericType Values = { 10 }; // iValue = 10
cout << Values.iValue << endl;
Values.dValue = 3.1416;
cout << Values.dValue << endl;
}
/* Output:
10
3.141600
*/
The NumericType union is arranged in memory (conceptually) as shown in the following figure.
Anonymous union
An anonymous union is one declared without a class-name or declarator-list .
union { member-list }
Names declared in an anonymous union are used directly, like nonmember variables. It implies that the names
declared in an anonymous union must be unique in the surrounding scope.
An anonymous union is subject to these additional restrictions:
If declared in file or namespace scope, it must also be declared as static .
It can have only public members; having private and protected members in an anonymous union
generates errors.
It can't have member functions.
See also
Classes and Structs
Keywords
class
struct
Functions (C++)
3/6/2021 • 13 minutes to read • Edit Online
A function is a block of code that performs some operation. A function can optionally define input parameters
that enable callers to pass arguments into the function. A function can optionally return a value as output.
Functions are useful for encapsulating common operations in a single reusable block, ideally with a name that
clearly describes what the function does. The following function accepts two integers from a caller and returns
their sum; a and b are parameters of type int .
The function can be invoked, or called, from any number of places in the program. The values that are passed to
the function are the arguments, whose types must be compatible with the parameter types in the function
definition.
int main()
{
int i = sum(10, 32);
int j = sum(i, 66);
cout << "The value of j is" << j << endl; // 108
}
There is no practical limit to function length, but good design aims for functions that perform a single well-
defined task. Complex algorithms should be broken up into easy-to-understand simpler functions whenever
possible.
Functions that are defined at class scope are called member functions. In C++, unlike other languages, a
function can also be defined at namespace scope (including the implicit global namespace). Such functions are
called free functions or non-member functions; they are used extensively in the Standard Library.
Functions may be overloaded, which means different versions of a function may share the same name if they
differ by the number and/or type of formal parameters. For more information, see Function Overloading.
A function definition consists of a declaration, plus the body, which is all the code between the curly braces:
#include <type_traits>
Function definitions
A function definition consists of the declaration and the function body, enclosed in curly braces, which contains
variable declarations, statements and expressions. The following example shows a complete function definition:
Variables declared inside the body are called local variables or locals. They go out of scope when the function
exits; therefore, a function should never return a reference to a local!
Function Templates
A function template is similar to a class template; it generates concrete functions based on the template
arguments. In many cases, the template is able to infer the type arguments and therefore it isn't necessary to
explicitly specify them.
When a function modifies an argument that is passed by reference, it modifies the original object, not a local
copy. To prevent a function from modifying such an argument, qualify the parameter as const&:
C++ 11: To explicitly handle arguments that are passed by rvalue-reference or lvalue-reference, use a double-
ampersand on the parameter to indicate a universal reference:
A function declared with the single keyword void in the parameter declaration list takes no arguments, as long
as the keyword void is the first and only member of the argument declaration list. Arguments of type void
elsewhere in the list produce errors. For example:
// OK same as GetTickCount()
long GetTickCount( void );
Note that, while it is illegal to specify a void argument except as outlined here, types derived from type void
(such as pointers to void and arrays of void ) can appear anywhere the argument declaration list.
Default Arguments
The last parameter or parameters in a function signature may be assigned a default argument, which means that
the caller may leave out the argument when calling the function unless they want to specify some other value.
When auto is used in conjunction with a trailing return type, it just serves as a placeholder for whatever the
decltype expression produces, and does not itself perform type deduction.
Note that auto does not preserve the const-ness of the type it deduces. For forwarding functions whose return
value needs to preserve the const-ness or ref-ness of its arguments, you can use the decltype(auto) keyword,
which uses the decltype type inference rules and preserves all the type information. decltype(auto) may be
used as an ordinary return value on the left side, or as a trailing return value.
The following example (based on code from N3493), shows decltype(auto) being used to enable perfect
forwarding of function arguments in a return type that isn't known until the template is instantiated.
struct S
{
string name;
int num;
};
S g()
{
string t{ "hello" };
int u{ 42 };
return { t, u };
}
int main()
{
S s = g();
cout << s.name << " " << s.num << endl;
return 0;
}
#include <tuple>
#include <string>
#include <iostream>
int main()
{
auto t = f();
cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
// --or--
int myval;
string myname;
double mydecimal;
tie(myval, myname, mydecimal) = f();
cout << myval << " " << myname << " " << mydecimal << endl;
return 0;
}
3. Visual Studio 2017 version 15.3 and later (available with /std:c++17 ): Use structured bindings. The
advantage of structured bindings is that the variables that store the return values are initialized at the
same time they are declared, which in some cases can be significantly more efficient. In the statement
auto[x, y, z] = f(); the brackets introduce and initialize names that are in scope for the entire function
block.
#include <tuple>
#include <string>
#include <iostream>
S g()
{
string t{ "hello" };
int u{ 42 };
return { t, u };
}
int main()
{
auto[x, y, z] = f(); // init from tuple
cout << x << " " << y << " " << z << endl;
4. In addition to using the return value itself, you can "return" values by defining any number of parameters
to use pass-by-reference so that the function can modify or initialize the values of objects that the caller
provides. For more information, see Reference-Type Function Arguments.
Function pointers
C++ supports function pointers in the same manner as the C language. However a more type-safe alternative is
usually to use a function object.
It is recommended that typedef be used to declare an alias for the function pointer type if declaring a function
that returns a function pointer type. For example
If this is not done, the proper syntax for the function declaration may be deduced from the declarator syntax for
the function pointer by replacing the identifier ( fp in the above example) with the functions name and
argument list, as follows:
Function declarations in which the last member of is the ellipsis (...) can take a variable number of arguments. In
these cases, C++ provides type checking only for the explicitly declared arguments. You can use variable
argument lists when you need to make a function so general that even the number and types of arguments can
vary. The family of functions is an example of functions that use variable argument lists. printf argument-
declaration-list
// variable_argument_lists.cpp
#include <stdio.h>
#include <stdarg.h>
case 'f':
Printable.f = va_arg( vl, double );
printf_s( "%f\n", Printable.f );
break;
case 'c':
Printable.c = va_arg( vl, char );
printf_s( "%c\n", Printable.c );
break;
case 's':
Printable.s = va_arg( vl, char * );
printf_s( "%s\n", Printable.s );
break;
default:
break;
}
}
va_end( vl );
}
//Output:
// 32.400002
// a
// Test string
C++ allows specification of more than one function of the same name in the same scope. These functions are
called overloaded functions. Overloaded functions enable you to supply different semantics for a function,
depending on the types and number of arguments.
For example, a print function that takes a std::string argument might perform very different tasks than one
that takes an argument of type double . Overloading saves you from having to use names such as print_string
or print_double . At compile time, the compiler chooses which overload to use based on the type of arguments
passed in by the caller. If you call print(42.0) , then the void print(double d) function will be invoked. If you
call print("hello world") , then the void print(std::string) overload will be invoked.
You can overload both member functions and non-member functions. The following table shows what parts of a
function declaration C++ uses to differentiate between groups of functions with the same name in the same
scope.
Overloading Considerations
F UN C T IO N DEC L A RAT IO N EL EM EN T USED F O R O VERLO A DIN G?
Ref-qualifiers Yes
Example
The following example illustrates how overloading can be used.
// function_overloading.cpp
// compile with: /EHsc
#include <iostream>
#include <math.h>
#include <string>
// Print a string.
int print(string s)
{
cout << s << endl;
return cout.good();
}
The preceding code shows overloading of the print function in file scope.
The default argument isn't considered part of the function type. Therefore, it's not used in selecting overloaded
functions. Two functions that differ only in their default arguments are considered multiple definitions rather
than overloaded functions.
Default arguments can't be supplied for overloaded operators.
Argument Matching
Overloaded functions are selected for the best match of function declarations in the current scope to the
arguments supplied in the function call. If a suitable function is found, that function is called. "Suitable" in this
context means either:
An exact match was found.
A trivial conversion was performed.
An integral promotion was performed.
A standard conversion to the desired argument type exists.
A user-defined conversion (either conversion operator or constructor) to the desired argument type
exists.
Arguments represented by an ellipsis were found.
The compiler creates a set of candidate functions for each argument. Candidate functions are functions in which
the actual argument in that position can be converted to the type of the formal argument.
A set of "best matching functions" is built for each argument, and the selected function is the intersection of all
the sets. If the intersection contains more than one function, the overloading is ambiguous and generates an
error. The function that is eventually selected is always a better match than every other function in the group for
at least one argument. If there's no clear winner, the function call generates an error.
Consider the following declarations (the functions are marked Variant 1 , Variant 2 , and Variant 3 , for
identification in the following discussion):
F1 = Add( F2, 23 );
Variant 3
Functions in Set 2 are functions for which there are implicit conversions from actual parameter type to formal
parameter type, and among such functions there's a function for which the "cost" of converting the actual
parameter type to its formal parameter type is the smallest.
The intersection of these two sets is Variant 1. An example of an ambiguous function call is:
F1 = Add( 3, 6 );
Variant 2 ( int can be converted to long using a Variant 1 ( int can be converted to long using a
standard conversion) standard conversion)
Because the intersection of these two sets is empty, the compiler generates an error message.
For argument matching, a function with n default arguments is treated as n+1 separate functions, each with a
different number of arguments.
The ellipsis (...) acts as a wildcard; it matches any actual argument. It can lead to many ambiguous sets, if you
don't design your overloaded function sets with extreme care.
NOTE
Ambiguity of overloaded functions can't be determined until a function call is encountered. At that point, the sets are built
for each argument in the function call, and you can determine whether an unambiguous overload exists. This means that
ambiguities can remain in your code until they are evoked by a particular function call.
int main() {
Over o1; // Calls default constructor.
Over o2( o1 ); // Calls Over( Over& ).
const Over o3; // Calls default constructor.
Over o4( o3 ); // Calls Over( const Over& ).
volatile Over o5; // Calls default constructor.
Over o6( o5 ); // Calls Over( volatile Over& ).
}
Output
Pointers to const and volatile objects are also considered different from pointers to the base type for the
purposes of overloading.
The first sequence, although it achieves the desired goal, isn't the best matching sequence — a shorter sequence
exists.
The following table shows a group of conversions, called trivial conversions, that have a limited effect on
determining which sequence is the best matching. The instances in which trivial conversions affect choice of
sequence are discussed in the list following the table.
Trivial Conversions
C O N VERT F RO M T Y P E C O N VERT TO T Y P E
type-name [ ] type-name *
This same rule applies to reference conversions. Conversion from type D& to type C& is preferable to
conversion from type D& to type B& , and so on.
This same rule applies to pointer-to-member conversions. Conversion from type T D::* to type T C::* is
preferable to conversion from type T D::* to type T B::* , and so on (where T is the type of the member).
The preceding rule applies only along a given path of derivation. Consider the graph shown in the following
figure.
// argument_matching1.cpp
class UDC
{
public:
operator int()
{
return 0;
}
operator long();
};
UDC udc;
int main()
{
Print( udc );
}
The available user-defined conversions for class UDC are from type int and type long . Therefore, the
compiler considers conversions for the type of the object being matched: UDC . A conversion to int exists, and
it is selected.
During the process of matching arguments, standard conversions can be applied to both the argument and the
result of a user-defined conversion. Therefore, the following code works:
In the preceding example, the user-defined conversion, operator long , is invoked to convert udc to type long
. If no user-defined conversion to type long had been defined, the conversion would have proceeded as follows:
Type UDC would have been converted to type int using the user-defined conversion. Then the standard
conversion from type int to type long would have been applied to match the argument in the declaration.
If any user-defined conversions are required to match an argument, the standard conversions aren't used when
evaluating the best match. Even if more than one candidate function requires a user-defined conversion, the
functions are considered equal. For example:
// argument_matching2.cpp
// C2668 expected
class UDC1
{
public:
UDC1( int ); // User-defined conversion from int.
};
class UDC2
{
public:
UDC2( long ); // User-defined conversion from long.
};
int main()
{
Func( 1 );
}
Both versions of Func require a user-defined conversion to convert type int to the class type argument. The
possible conversions are:
Convert from type int to type UDC1 (a user-defined conversion).
Convert from type int to type long ; then convert to type UDC2 (a two-step conversion).
Even though the second one requires both a standard conversion and the user-defined conversion, the two
conversions are still considered equal.
NOTE
User-defined conversions are considered conversion by construction or conversion by initialization (conversion function).
Both methods are considered equal when considering the best match.
The left operand of the ->* and .* (pointer to member) operators are treated the same way as the . and
-> (member-selection) operators with respect to argument matching.
class C
{
public:
C() {/*expensive initialization*/}
vector<unsigned> get_data() &
{
cout << "lvalue\n";
return _data;
}
vector<unsigned> get_data() &&
{
cout << "rvalue\n";
return std::move(_data);
}
private:
vector<unsigned> _data;
};
int main()
{
C c;
auto v = c.get_data(); // get a copy. prints "lvalue".
auto v2 = C().get_data(); // get the original. prints "rvalue"
return 0;
}
Restrictions on overloading
Several restrictions govern an acceptable set of overloaded functions:
Any two functions in a set of overloaded functions must have different argument lists.
Overloading functions with argument lists of the same types, based on return type alone, is an error.
Microsoft Specific
You can overload operator new solely on the basis of return type — specifically, on the basis of the memory-
model modifier specified.
END Microsoft Specific
Member functions can't be overloaded solely on the basis of one being static and the other nonstatic.
typedef declarations do not define new types; they introduce synonyms for existing types. They don't
affect the overloading mechanism. Consider the following code:
The preceding two functions have identical argument lists. PSTR is a synonym for type char * . In
member scope, this code generates an error.
Enumerated types are distinct types and can be used to distinguish between overloaded functions.
The types "array of " and "pointer to" are considered identical for the purposes of distinguishing between
overloaded functions, but only for singly dimensioned arrays. That's why these overloaded functions
conflict and generate an error message:
For multiply dimensioned arrays, the second and all succeeding dimensions are considered part of the
type. Therefore, they are used in distinguishing between overloaded functions:
// declaration_matching1.cpp
// compile with: /EHsc
#include <iostream>
int main()
{
// Declare func local to main.
extern void func( char *sz );
The preceding code shows two definitions from the function func . The definition that takes an argument of
type char * is local to main because of the extern statement. Therefore, the definition that takes an argument
of type int is hidden, and the first call to func is in error.
For overloaded member functions, different versions of the function can be given different access privileges.
They are still considered to be in the scope of the enclosing class and thus are overloaded functions. Consider
the following code, in which the member function Deposit is overloaded; one version is public, the other,
private.
The intent of this sample is to provide an Account class in which a correct password is required to perform
deposits. It's done by using overloading.
The call to Deposit in Account::Deposit calls the private member function. This call is correct because
Account::Deposit is a member function, and has access to the private members of the class.
// declaration_matching2.cpp
class Account
{
public:
Account()
{
}
double Deposit( double dAmount, char *szPassword );
private:
double Deposit( double dAmount )
{
return 0.0;
}
int Validate( char *szPassword )
{
return 0;
}
};
int main()
{
// Allocate a new object of type Account.
Account *pAcct = new Account;
See also
Functions (C++)
Explicitly Defaulted and Deleted Functions
3/6/2021 • 6 minutes to read • Edit Online
In C++11, defaulted and deleted functions give you explicit control over whether the special member functions
are automatically generated. Deleted functions also give you simple language to prevent problematic type
promotions from occurring in arguments to functions of all types—special member functions, as well as normal
member functions and non-member functions—which would otherwise cause an unwanted function call.
NOTE
Additionally, the C++11 standard specifies the following additional rules:
If a copy constructor or destructor is explicitly declared, then automatic generation of the copy-assignment operator is
deprecated.
If a copy-assignment operator or destructor is explicitly declared, then automatic generation of the copy constructor is
deprecated.
In both cases, Visual Studio continues to automatically generate the necessary functions implicitly, and does not emit a
warning.
The consequences of these rules can also leak into object hierarchies. For example, if for any reason a base class
fails to have a default constructor that's callable from a deriving class—that is, a public or protected
constructor that takes no parameters—then a class that derives from it cannot automatically generate its own
default constructor.
These rules can complicate the implementation of what should be straight-forward, user-defined types and
common C++ idioms—for example, making a user-defined type non-copyable by declaring the copy
constructor and copy-assignment operator privately and not defining them.
struct noncopyable
{
noncopyable() {};
private:
noncopyable(const noncopyable&);
noncopyable& operator=(const noncopyable&);
};
Before C++11, this code snippet was the idiomatic form of non-copyable types. However, it has several
problems:
The copy constructor has to be declared privately to hide it, but because it's declared at all, automatic
generation of the default constructor is prevented. You have to explicitly define the default constructor if
you want one, even if it does nothing.
Even if the explicitly-defined default constructor does nothing, it's considered non-trivial by the compiler.
It's less efficient than an automatically generated default constructor and prevents noncopyable from
being a true POD type.
Even though the copy constructor and copy-assignment operator are hidden from outside code, the
member functions and friends of noncopyable can still see and call them. If they are declared but not
defined, calling them causes a linker error.
Although this is a commonly accepted idiom, the intent is not clear unless you understand all of the rules
for automatic generation of the special member functions.
In C++11, the non-copyable idiom can be implemented in a way that is more straightforward.
struct noncopyable
{
noncopyable() =default;
noncopyable(const noncopyable&) =delete;
noncopyable& operator=(const noncopyable&) =delete;
};
Notice how the problems with the pre-C++11 idiom are resolved:
Generation of the default constructor is still prevented by declaring the copy constructor, but you can
bring it back by explicitly defaulting it.
Explicitly defaulted special member functions are still considered trivial, so there is no performance
penalty, and noncopyable is not prevented from being a true POD type.
The copy constructor and copy-assignment operator are public but deleted. It is a compile-time error to
define or call a deleted function.
The intent is clear to anyone who understands =default and =delete . You don't have to understand the
rules for automatic generation of special member functions.
Similar idioms exist for making user-defined types that are non-movable, that can only be dynamically allocated,
or that cannot be dynamically allocated. Each of these idioms have pre-C++11 implementations that suffer
similar problems, and that are similarly resolved in C++11 by implementing them in terms of defaulted and
deleted special member functions.
Explicitly defaulted functions
You can default any of the special member functions—to explicitly state that the special member function uses
the default implementation, to define the special member function with a non-public access qualifier, or to
reinstate a special member function whose automatic generation was prevented by other circumstances.
You default a special member function by declaring it as in this example:
struct widget
{
widget()=default;
Notice that you can default a special member function outside the body of a class as long as it's inlinable.
Because of the performance benefits of trivial special member functions, we recommend that you prefer
automatically generated special member functions over empty function bodies when you want the default
behavior. You can do this either by explicitly defaulting the special member function, or by not declaring it (and
also not declaring other special member functions that would prevent it from being automatically generated.)
Deleted functions
You can delete special member functions as well as normal member functions and non-member functions to
prevent them from being defined or called. Deleting of special member functions provides a cleaner way of
preventing the compiler from generating special member functions that you don't want. The function must be
deleted as it is declared; it cannot be deleted afterwards in the way that a function can be declared and then later
defaulted.
struct widget
{
// deleted operator new prevents widget from being dynamically allocated.
void* operator new(std::size_t) = delete;
};
Deleting of normal member function or non-member functions prevents problematic type promotions from
causing an unintended function to be called. This works because deleted functions still participate in overload
resolution and provide a better match than the function that could be called after the types are promoted. The
function call resolves to the more-specific—but deleted—function and causes a compiler error.
// deleted overload prevents call through type promotion of float to double from succeeding.
void call_with_true_double_only(float) =delete;
void call_with_true_double_only(double param) { return; }
Notice in the preceding sample that calling call_with_true_double_only by using a float argument would
cause a compiler error, but calling call_with_true_double_only by using an int argument would not; in the
int case, the argument will be promoted from int to double and successfully call the double version of the
function, even though that might not be what's intended. To ensure that any call to this function by using a non-
double argument causes a compiler error, you can declare a template version of the function that's deleted.
template < typename T >
void call_with_true_double_only(T) =delete; //prevent call through type promotion of any T to double from
succeeding.
void call_with_true_double_only(double param) { return; } // also define for const double, double&, etc. as
needed.
Argument-Dependent Name (Koenig) Lookup on
Functions
3/6/2021 • 2 minutes to read • Edit Online
The compiler can use argument-dependent name lookup to find the definition of an unqualified function call.
Argument-dependent name lookup is also called Koenig lookup. The type of every argument in a function call is
defined within a hierarchy of namespaces, classes, structures, unions, or templates. When you specify an
unqualified postfix function call, the compiler searches for the function definition in the hierarchy associated
with each argument type.
Example
In the sample, the compiler notes that function f() takes an argument x . Argument x is of type A::X , which
is defined in namespace A . The compiler searches namespace A and finds a definition for function f() that
takes an argument of type A::X .
// argument_dependent_name_koenig_lookup_on_functions.cpp
namespace A
{
struct X
{
};
void f(const X&)
{
}
}
int main()
{
// The compiler finds A::f() in namespace A, which is where
// the type of argument x is defined. The type of x is A::X.
A::X x;
f(x);
}
Default Arguments
3/6/2021 • 2 minutes to read • Edit Online
In many cases, functions have arguments that are used so infrequently that a default value would suffice. To
address this, the default-argument facility allows for specifying only those arguments to a function that are
meaningful in a given call. To illustrate this concept, consider the example presented in Function Overloading.
In many applications, a reasonable default can be supplied for prec , eliminating the need for two functions:
The implementation of the print function is changed slightly to reflect the fact that only one such function
exists for type double :
// default_arguments.cpp
// compile with: /EHsc /c
#include <iostream>
#include <math.h>
using namespace std;
To invoke the new print function, use code such as the following:
print( d ); // Precision of 2 supplied by default argument.
print( d, 0 ); // Override default argument to achieve other
// results.
A default argument cannot be redefined in later declarations even if the redefinition is identical to the
original. Therefore, the following code produces an error:
...
The problem with this code is that the function declaration in the definition redefines the default
argument for prec .
Additional default arguments can be added by later declarations.
Default arguments can be provided for pointers to functions. For example:
Example
In the following class declaration, the Account constructor is an inline function. The member functions
GetBalance , Deposit , and Withdraw aren't specified as inline but can be implemented as inline functions.
// Inline_Member_Functions.cpp
class Account
{
public:
Account(double initial_balance) { balance = initial_balance; }
double GetBalance();
double Deposit( double Amount );
double Withdraw( double Amount );
private:
double balance;
};
NOTE
In the class declaration, the functions were declared without the inline keyword. The inline keyword can be
specified in the class declaration; the result is the same.
A given inline member function must be declared the same way in every compilation unit. This constraint causes
inline functions to behave as if they were instantiated functions. Additionally, there must be exactly one
definition of an inline function.
A class member function defaults to external linkage unless a definition for that function contains the inline
specifier. The preceding example shows that you don't have to declare these functions explicitly with the inline
specifier. Using inline in the function definition causes it to be an inline function. However, it's not allowed to
redeclare a function as inline after a call to that function.
inline , __inline , and __forceinline
The inline and __inline specifiers instruct the compiler to insert a copy of the function body into each place
the function is called.
The insertion, called inline expansion or inlining, occurs only if the compiler's cost-benefit analysis shows it's
worthwhile. Inline expansion minimizes the function-call overhead at the potential cost of larger code size.
The __forceinline keyword overrides the cost-benefit analysis and relies on the judgment of the programmer
instead. Exercise caution when using __forceinline . Indiscriminate use of __forceinline can result in larger
code with only marginal performance gains or, in some cases, even performance losses (because of the
increased paging of a larger executable, for example).
Using inline functions can make your program faster because they eliminate the overhead associated with
function calls. Functions expanded inline are subject to code optimizations not available to normal functions.
The compiler treats the inline expansion options and keywords as suggestions. There's no guarantee that
functions will be inlined. You can't force the compiler to inline a particular function, even with the __forceinline
keyword. When compiling with /clr , the compiler won't inline a function if there are security attributes applied
to the function.
The inline keyword is available only in C++. The __inline and __forceinline keywords are available in both
C and C++. For compatibility with previous versions, _inline and _forceinline are synonyms for __inline ,
and __forceinline unless compiler option /Za (Disable language extensions) is specified.
The inline keyword tells the compiler that inline expansion is preferred. However, the compiler can create a
separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code
inline. Two cases where this behavior can happen are:
Recursive functions.
Functions that are referred to through a pointer elsewhere in the translation unit.
These reasons may interfere with inlining, as may others, at the discretion of the compiler; you shouldn't depend
on the inline specifier to cause a function to be inlined.
As with normal functions, there's no defined order for argument evaluation in an inline function. In fact, it could
be different from the argument evaluation order when passed using the normal function-call protocol.
The /Ob compiler optimization option helps to determine whether inline function expansion actually occurs.
/LTCG does cross-module inlining whether it's requested in source code or not.
Example 1
// inline_keyword1.cpp
// compile with: /c
inline int max( int a , int b ) {
if( a > b )
return a;
return b;
}
A class's member functions can be declared inline, either by using the inline keyword or by placing the
function definition within the class definition.
Example 2
// inline_keyword2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;
class MyClass {
public:
void print() { cout << i << ' '; } // Implicitly inline
private:
int i;
};
Microsoft-specific
The __inline keyword is equivalent to inline .
Even with __forceinline , the compiler can't inline code in all circumstances. The compiler can't inline a function
if:
The function or its caller is compiled with /Ob0 (the default option for debug builds).
The function and the caller use different types of exception handling (C++ exception handling in one,
structured exception handling in the other).
The function has a variable argument list.
The function uses inline assembly, unless compiled with /Ox , /O1 , or /O2 .
The function is recursive and doesn't have #pragma inline_recursion(on) set. With the pragma, recursive
functions are inlined to a default depth of 16 calls. To reduce the inlining depth, use inline_depth
pragma.
The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
The program takes the address of the function and the call is made via the pointer to the function. Direct
calls to functions that have had their address taken can be inlined.
The function is also marked with the naked __declspec modifier.
If the compiler can't inline a function declared with __forceinline , it generates a level 1 warning, except when:
The function is compiled by using /Od or /Ob0. No inlining is expected in these cases.
The function is defined externally, in an included library or another translation unit, or is a virtual call
target or indirect call target. The compiler can't identify non-inlined code that it can't find in the current
translation unit.
Recursive functions can be replaced with inline code to a depth specified by the inline_depth pragma, up to a
maximum of 16 calls. After that depth, recursive function calls are treated as calls to an instance of the function.
The depth to which recursive functions are examined by the inline heuristic can't exceed 16. The
inline_recursion pragma controls the inline expansion of a function currently under expansion. See the Inline-
Function Expansion (/Ob) compiler option for related information.
END Microsoft Specific
For more information on using the inline specifier, see:
Inline Class Member Functions
Defining Inline C++ Functions with dllexport and dllimport
When to use inline functions
Inline functions are best used for small functions such as accessing private data members. The main purpose of
these one- or two-line "accessor" functions is to return state information about objects. Short functions are
sensitive to the overhead of function calls. Longer functions spend proportionately less time in the calling and
returning sequence and benefit less from inlining.
A Point class can be defined as follows:
// when_to_use_inline_functions.cpp
class Point
{
public:
// Define "accessor" functions as
// reference types.
unsigned& x();
unsigned& y();
private:
unsigned _x;
unsigned _y;
};
Assuming coordinate manipulation is a relatively common operation in a client of such a class, specifying the
two accessor functions ( x and y in the preceding example) as inline typically saves the overhead on:
Function calls (including parameter passing and placing the object's address on the stack)
Preservation of caller's stack frame
New stack frame setup
Return-value communication
Restoring the old stack frame
Return
Expressions passed as arguments to inline functions are evaluated once. In some cases, expressions
passed as arguments to macros can be evaluated more than once.
The following example shows a macro that converts lowercase letters to uppercase:
// inline_functions_macro.c
#include <stdio.h>
#include <conio.h>
#define toupper(a) ((a) >= 'a' && ((a) <= 'z') ? ((a)-('a'-'A')):(a))
int main() {
char ch;
printf_s("Enter a character: ");
ch = toupper( getc(stdin) );
printf_s( "%c", ch );
}
// Sample Input: xyz
// Sample Output: Z
The intent of the expression toupper(getc(stdin)) is that a character should be read from the console device (
stdin ) and, if necessary, converted to uppercase.
Because of the implementation of the macro, getc is executed once to determine whether the character is
greater than or equal to "a," and once to determine whether it's less than or equal to "z." If it is in that range,
getc is executed again to convert the character to uppercase. It means the program waits for two or three
characters when, ideally, it should wait for only one.
Inline functions remedy the problem previously described:
// inline_functions_inline.cpp
#include <stdio.h>
#include <conio.h>
int main() {
printf_s("Enter a character: ");
char ch = toupper( getc(stdin) );
printf_s( "%c", ch );
}
Sample Input: a
Sample Output: A
See also
noinline
auto_inline
Operator overloading
3/6/2021 • 2 minutes to read • Edit Online
The operator keyword declares a function specifying what operator-symbol means when applied to instances
of a class. This gives the operator more than one meaning, or "overloads" it. The compiler distinguishes between
the different meanings of an operator by examining the types of its operands.
Syntax
type operator operator-symbol ( parameter-list )
Remarks
You can redefine the function of most built-in operators globally or on a class-by-class basis. Overloaded
operators are implemented as functions.
The name of an overloaded operator is operator x, where x is the operator as it appears in the following table.
For example, to overload the addition operator, you define a function called operator+ . Similarly, to overload
the addition/assignment operator, += , define a function called operator+= .
Redefinable Operators
O P ERATO R NAME TYPE
, Comma Binary
!= Inequality Binary
% Modulus Binary
() Function call —
* Multiplication Binary
+ Addition Binary
++ Increment 1 Unary
- Subtraction Binary
-- Decrement 1 Unary
/ Division Binary
= Assignment Binary
== Equality Binary
[] Array subscript —
^ Exclusive OR Binary
O P ERATO R NAME TYPE
|| Logical OR Binary
delete Delete —
new New —
1 Two versions of the unary increment and decrement operators exist: preincrement and postincrement.
See General Rules for Operator Overloading for more information. The constraints on the various categories of
overloaded operators are described in the following topics:
Unary Operators
Binary Operators
Assignment
Function Call
Subscripting
Class-Member Access
Increment and Decrement.
User-Defined Type Conversions
The operators shown in the following table cannot be overloaded. The table includes the preprocessor symbols
# and ## .
Nonredefinable Operators
O P ERATO R NAME
. Member selection
.* Pointer-to-member selection
:: Scope resolution
?: Conditional
## Preprocessor concatenate
Although overloaded operators are usually called implicitly by the compiler when they are encountered in code,
they can be invoked explicitly the same way as any member or nonmember function is called:
Point pt;
pt.operator+( 3 ); // Call addition operator to add 3 to pt.
Example
The following example overloads the + operator to add two complex numbers and returns the result.
// operator_overloading.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct Complex {
Complex( double r, double i ) : re(r), im(i) {}
Complex operator+( Complex &other );
void Display( ) { cout << re << ", " << im << endl; }
private:
double re, im;
};
int main() {
Complex a = Complex( 1.2, 3.4 );
Complex b = Complex( 5.6, 7.8 );
Complex c = Complex( 0.0, 0.0 );
c = a + b;
c.Display();
}
6.8, 11.2
In this section
General Rules for Operator Overloading
Overloading Unary Operators
Binary Operators
Assignment
Function Call
Subscripting
Member Access
See also
C++ Built-in Operators, Precedence and Associativity
Keywords
General Rules for Operator Overloading
3/6/2021 • 2 minutes to read • Edit Online
The following rules constrain how overloaded operators are implemented. However, they do not apply to the
new and delete operators, which are covered separately.
You cannot define new operators, such as ..
You cannot redefine the meaning of operators when applied to built-in data types.
Overloaded operators must either be a nonstatic class member function or a global function. A global
function that needs access to private or protected class members must be declared as a friend of that
class. A global function must take at least one argument that is of class or enumerated type or that is a
reference to a class or enumerated type. For example:
// rules_for_operator_overloading.cpp
class Point
{
public:
Point operator<( Point & ); // Declare a member operator
// overload.
// Declare addition operators.
friend Point operator+( Point&, int );
friend Point operator+( int, Point& );
};
int main()
{
}
The preceding code sample declares the less-than operator as a member function; however, the addition
operators are declared as global functions that have friend access. Note that more than one
implementation can be provided for a given operator. In the case of the preceding addition operator, the
two implementations are provided to facilitate commutativity. It is just as likely that operators that add a
Point to a Point , int to a Point , and so on, might be implemented.
Operators obey the precedence, grouping, and number of operands dictated by their typical use with
built-in types. Therefore, there is no way to express the concept "add 2 and 3 to an object of type Point ,"
expecting 2 to be added to the x coordinate and 3 to be added to the y coordinate.
Unary operators declared as member functions take no arguments; if declared as global functions, they
take one argument.
Binary operators declared as member functions take one argument; if declared as global functions, they
take two arguments.
If an operator can be used as either a unary or a binary operator (& , * , + , and - ), you can overload each
use separately.
Overloaded operators cannot have default arguments.
All overloaded operators except assignment (operator= ) are inherited by derived classes.
The first argument for member-function overloaded operators is always of the class type of the object for
which the operator is invoked (the class in which the operator is declared, or a class derived from that
class). No conversions are supplied for the first argument.
Note that the meaning of any of the operators can be changed completely. That includes the meaning of the
address-of (& ), assignment (= ), and function-call operators. Also, identities that can be relied upon for built-in
types can be changed using operator overloading. For example, the following four statements are usually
equivalent when completely evaluated:
var = var + 1;
var += 1;
var++;
++var;
This identity cannot be relied upon for class types that overload operators. Moreover, some of the requirements
implicit in the use of these operators for basic types are relaxed for overloaded operators. For example, the
addition/assignment operator, += , requires the left operand to be an l-value when applied to basic types; there
is no such requirement when the operator is overloaded.
NOTE
For consistency, it is often best to follow the model of the built-in types when defining overloaded operators. If the
semantics of an overloaded operator differ significantly from its meaning in other contexts, it can be more confusing than
useful.
See also
Operator Overloading
Overloading Unary Operators
3/6/2021 • 2 minutes to read • Edit Online
ret-type operator op ()
where ret-type is the return type and op is one of the operators listed in the preceding table.
To declare a unary operator function as a global function, you must declare it in the form:
where ret-type and op are as described for member operator functions and the arg is an argument of class type
on which to operate.
NOTE
There is no restriction on the return types of the unary operators. For example, it makes sense for logical NOT ( ! ) to
return an integral value, but this is not enforced.
See also
Operator Overloading
Increment and Decrement Operator Overloading
(C++)
3/6/2021 • 2 minutes to read • Edit Online
The increment and decrement operators fall into a special category because there are two variants of each:
Preincrement and postincrement
Predecrement and postdecrement
When you write overloaded operator functions, it can be useful to implement separate versions for the prefix
and postfix versions of these operators. To distinguish between the two, the following rule is observed: The
prefix form of the operator is declared exactly the same way as any other unary operator; the postfix form
accepts an additional argument of type int .
NOTE
When specifying an overloaded operator for the postfix form of the increment or decrement operator, the additional
argument must be of type int ; specifying any other type generates an error.
The following example shows how to define prefix and postfix increment and decrement operators for the
Point class:
// increment_and_decrement1.cpp
class Point
{
public:
// Declare prefix and postfix increment operators.
Point& operator++(); // Prefix increment operator.
Point operator++(int); // Postfix increment operator.
The same operators can be defined in file scope (globally) using the following function heads:
// increment_and_decrement2.cpp
class Int
{
public:
Int &operator++( int n );
private:
int _i;
};
There is no syntax for using the increment or decrement operators to pass these values other than explicit
invocation, as shown in the preceding code. A more straightforward way to implement this functionality is to
overload the addition/assignment operator (+= ).
See also
Operator Overloading
Binary Operators
3/6/2021 • 2 minutes to read • Edit Online
, Comma
!= Inequality
% Modulus
%= Modulus/assignment
* Multiplication
*= Multiplication/assignment
+ Addition
+= Addition/assignment
- Subtraction
-= Subtraction/assignment
/ Division
/= Division/assignment
= Assignment
== Equality
^ Exclusive OR
^= Exclusive OR/assignment
| Bitwise inclusive OR
|| Logical OR
To declare a binary operator function as a nonstatic member, you must declare it in the form:
where ret-type is the return type, op is one of the operators listed in the preceding table, and arg is an argument
of any type.
To declare a binary operator function as a global function, you must declare it in the form:
where ret-type and op are as described for member operator functions and arg1 and arg2 are arguments. At
least one of the arguments must be of class type.
NOTE
There is no restriction on the return types of the binary operators; however, most user-defined binary operators return
either a class type or a reference to a class type.
See also
Operator Overloading
Assignment
3/6/2021 • 2 minutes to read • Edit Online
The assignment operator (= ) is, strictly speaking, a binary operator. Its declaration is identical to any other
binary operator, with the following exceptions:
It must be a nonstatic member function. No operator= can be declared as a nonmember function.
It is not inherited by derived classes.
A default operator= function can be generated by the compiler for class types, if none exists.
The following example illustrates how to declare an assignment operator:
class Point
{
public:
int _x, _y;
int main()
{
Point pt1, pt2;
pt1 = pt2;
}
The supplied argument is the right side of the expression. The operator returns the object to preserve the
behavior of the assignment operator, which returns the value of the left side after the assignment is complete.
This allows chaining of assignments, such as:
The copy assignment operator is not to be confused with the copy constructor. The latter is called during the
construction of a new object from an existing one:
See also
Operator Overloading
Copy Constructors and Copy Assignment Operators (C++)
Function Call (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
primary-expression ( expression-list )
Remarks
In this context, primary-expression is the first operand, and expression-list , a possibly empty list of
arguments, is the second operand. The function-call operator is used for operations that require a number of
parameters. This works because expression-list is a list instead of a single operand. The function-call operator
must be a nonstatic member function.
The function-call operator, when overloaded, does not modify how functions are called; rather, it modifies how
the operator is to be interpreted when applied to objects of a given class type. For example, the following code
would usually be meaningless:
Point pt;
pt( 3, 2 );
Given an appropriate overloaded function-call operator, however, this syntax can be used to offset the x
coordinate 3 units and the y coordinate 2 units. The following code shows such a definition:
// function_call.cpp
class Point
{
public:
Point() { _x = _y = 0; }
Point &operator()( int dx, int dy )
{ _x += dx; _y += dy; return *this; }
private:
int _x, _y;
};
int main()
{
Point pt;
pt( 3, 2 );
}
Note that the function-call operator is applied to the name of an object, not the name of a function.
You can also overload the function call operator using a pointer to a function (rather than the function itself).
typedef void(*ptf)();
void func()
{
}
struct S
{
operator ptf()
{
return func;
}
};
int main()
{
S s;
s();//operates as s.operator ptf()()
}
See also
Operator Overloading
Subscripting
3/6/2021 • 2 minutes to read • Edit Online
The subscript operator ([ ] ), like the function-call operator, is considered a binary operator. The subscript
operator must be a nonstatic member function that takes a single argument. This argument can be of any type
and designates the desired array subscript.
Example
The following example demonstrates how to create a vector of type int that implements bounds checking:
// subscripting.cpp
// compile with: /EHsc
#include <iostream>
// Construct an IntVector.
IntVector::IntVector( int cElements ) {
_iElements = new int[cElements];
_iUpperBound = cElements;
}
v[3] = v[9];
Comments
When i reaches 10 in the preceding program, operator[] detects that an out-of-bounds subscript is being
used and issues an error message.
Note that the function operator[] returns a reference type. This causes it to be an l-value, allowing you to use
subscripted expressions on either side of assignment operators.
See also
Operator Overloading
Member Access
3/6/2021 • 2 minutes to read • Edit Online
Class member access can be controlled by overloading the member access operator (-> ). This operator is
considered a unary operator in this usage, and the overloaded operator function must be a class member
function. Therefore, the declaration for such a function is:
Syntax
class-type *operator->()
Remarks
where class-type is the name of the class to which this operator belongs. The member access operator function
must be a nonstatic member function.
This operator is used (often in conjunction with the pointer-dereference operator) to implement "smart pointers"
that validate pointers prior to dereference or count usage.
The . member access operator cannot be overloaded.
See also
Operator Overloading
Classes and Structs (C++)
3/6/2021 • 2 minutes to read • Edit Online
This section introduces C++ classes and structs. The two constructs are identical in C++ except that in structs
the default accessibility is public, whereas in classes the default is private.
Classes and structs are the constructs whereby you define your own types. Classes and structs can both contain
data members and member functions, which enable you to describe the type's state and behavior.
The following topics are included:
class
struct
Class Member Overview
Member Access Control
Inheritance
Static Members
User-Defined Type Conversions
Mutable Data Members (mutable specifier)
Nested Class Declarations
Anonymous Class Types
Pointers to Members
this Pointer
C++ Bit Fields
The three class types are structure, class, and union. They are declared using the struct, class, and union
keywords. The following table shows the differences among the three class types.
For more information on unions, see Unions. For information on classes and structs in C++/CLI and C++/CX,
see Classes and Structs.
Access Control and Constraints of Structures, Classes and Unions
ST RUC T URES C L A SSES UN IO N S
See also
C++ Language Reference
class (C++)
3/6/2021 • 2 minutes to read • Edit Online
The class keyword declares a class type or defines an object of a class type.
Syntax
[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
member-list
} [declarators];
[ class ] tag declarators;
Parameters
template-spec
Optional template specifications. For more information, refer to Templates.
class
The class keyword.
ms-decl-spec
Optional storage-class specification. For more information, refer to the __declspec keyword.
tag
The type name given to the class. The tag becomes a reserved word within the scope of the class. The tag is
optional. If omitted, an anonymous class is defined. For more information, see Anonymous Class Types.
base-list
Optional list of classes or structures this class will derive its members from. See Base Classes for more
information. Each base class or structure name can be preceded by an access specifier (public, private, protected)
and the virtual keyword. See the member-access table in Controlling Access to Class Members for more
information.
member-list
List of class members. Refer to Class Member Overview for more information.
declarators
Declarator list specifying the names of one or more instances of the class type. Declarators may include
initializer lists if all data members of the class are public . This is more common in structures, whose data
members are public by default, than in classes. See Overview of Declarators for more information.
Remarks
For more information on classes in general, refer to one of the following topics:
struct
union
__multiple_inheritance
__single_inheritance
__virtual_inheritance
For information on managed classes and structs in C++/CLI and C++/CX, see Classes and Structs
Example
// class.cpp
// compile with: /EHsc
// Example of the class keyword
// Exhibits polymorphism/virtual functions.
#include <iostream>
#include <string>
using namespace std;
class dog
{
public:
dog()
{
_legs = 4;
_bark = true;
}
private:
string _dogSize, _earType;
int _legs;
bool _bark;
};
string getColor()
{
return _color;
}
protected:
string _color, _earLength, _earType;
};
int main()
{
{
dog mongrel;
breed labrador("yellow", "large");
mongrel.setEars("pointy");
labrador.setEars("long", "floppy");
cout << "Cody is a " << labrador.getColor() << " labrador" << endl;
}
See also
Keywords
Classes and Structs
struct (C++)
3/6/2021 • 2 minutes to read • Edit Online
The struct keyword defines a structure type and/or a variable of a structure type.
Syntax
[template-spec] struct [ms-decl-spec] [tag [: base-list ]]
{
member-list
} [declarators];
[struct] tag declarators;
Parameters
template-spec
Optional template specifications. For more information, refer to Template Specifications.
struct
The struct keyword.
ms-decl-spec
Optional storage-class specification. For more information, refer to the __declspec keyword.
tag
The type name given to the structure. The tag becomes a reserved word within the scope of the structure. The
tag is optional. If omitted, an anonymous structure is defined. For more information, see Anonymous Class
Types.
base-list
Optional list of classes or structures this structure will derive its members from. See Base Classes for more
information. Each base class or structure name can be preceded by an access specifier (public, private, protected)
and the virtual keyword. See the member-access table in Controlling Access to Class Members for more
information.
member-list
List of structure members. Refer to Class Member Overview for more information. The only difference here is
that struct is used in place of class .
declarators
Declarator list specifying the names of the structure. Declarator lists declare one or more instances of the
structure type. Declarators may include initializer lists if all data members of the structure are public . Initializer
lists are common in structures because data members are public by default. See Overview of Declarators for
more information.
Remarks
A structure type is a user-defined composite type. It is composed of fields or members that can have different
types.
In C++, a structure is the same as a class except that its members are public by default.
For information on managed classes and structs in C++/CLI, see Classes and Structs.
Using a Structure
In C, you must explicitly use the struct keyword to declare a structure. In C++, you do not need to use the
struct keyword after the type has been defined.
You have the option of declaring variables when the structure type is defined by placing one or more comma-
separated variable names between the closing brace and the semicolon.
Structure variables can be initialized. The initialization for each variable must be enclosed in braces.
For related information, see class, union, and enum.
Example
#include <iostream>
using namespace std;
int main() {
struct PERSON sister; // C style structure declaration
PERSON brother; // C++ style structure declaration
sister.age = 13; // assign values to members
brother.age = 7;
cout << "sister.age = " << sister.age << '\n';
cout << "brother.age = " << brother.age << '\n';
CELL my_cell;
my_cell.character = 1;
cout << "my_cell.character = " << my_cell.character;
}
// Output:
// sister.age = 13
// brother.age = 7
// my_cell.character = 1
Class Member Overview
3/6/2021 • 3 minutes to read • Edit Online
A class or struct consists of its members. The work that a class does is performed by its member functions. The
state that it maintains is stored in its data members. Initialization of members is done by constructors, and
cleanup work such as freeing of memory and releasing of resources is done by destructors. In C++11 and later,
data members can (and usually should) be initialized at the point of declaration.
NOTE
Friends are included in the preceding list because they are contained in the class declaration. However, they are
not true class members, because they are not in the scope of the class.
class TestRun
{
// Start member list.
Member accessibility
The members of a class are declared in the member list. The member list of a class may be divided into any
number of private , protected and public sections using keywords known as access specifiers. A colon : must
follow the access specifier. These sections need not be contiguous, that is, any of these keywords may appear
several times in the member list. The keyword designates the access of all members up until the next access
specifier or the closing brace. For more information, see Member Access Control (C++).
Static members
A data member may be declared as static, which means all objects of the class have access to the same copy of
it. A member function may be declared as static, in which case it can only access static data members of the class
(and has no this pointer). For more information, see Static Data Members.
Memberwise initialization
In C++11 and later, non-static member declarators can contain initializers.
class CanInit
{
public:
long num {7}; // OK in C++11
int k = 9; // OK in C++11
static int i = 9; // Error: must be defined and initialized
// outside of class declaration.
If a member is assigned a value in a constructor, that value overwrites the value with which the member was
initialized at the point of declaration.
There is only one shared copy of static data members for all objects of a given class type. Static data members
must be defined and can be initialized at file scope. (For more information about static data members, see Static
Data Members.) The following example shows how to perform these initializations:
// class_members2.cpp
class CanInit2
{
public:
CanInit2() {} // Initializes num to 7 when new objects of type
// CanInit are created.
long num {7};
static int i;
static int j;
};
// At file scope:
See also
Classes and Structs
Member Access Control (C++)
3/6/2021 • 6 minutes to read • Edit Online
Access controls enable you to separate the public interface of a class from the private implementation details
and the protected members that are only for use by derived classes. The access specifier applies to all members
declared after it until the next access specifier is encountered.
class Point
{
public:
Point( int, int ) // Declare public constructor.;
Point();// Declare public default constructor.
int &x( int ); // Declare public accessor.
int &y( int ); // Declare public accessor.
The default access is private in a class, and public in a struct or union. Access specifiers in a class can be used
any number of times in any order. The allocation of storage for objects of class types is implementation
dependent, but members are guaranteed to be assigned successively higher memory addresses between access
specifiers.
Member-Access Control
T Y P E O F A C C ESS M EA N IN G
Access control helps prevent you from using objects in ways they were not intended to be used. This protection
is lost when explicit type conversions (casts) are performed.
NOTE
Access control is equally applicable to all names: member functions, member data, nested classes, and enumerators.
Access Control in Derived Classes
Two factors control which members of a base class are accessible in a derived class; these same factors control
access to the inherited members in the derived class:
Whether the derived class declares the base class using the public access specifier.
What the access to the member is in the base class.
The following table shows the interaction between these factors and how to determine base-class member
access.
Member Access in Base Class
P RIVAT E P ROT EC T ED P UB L IC
Always inaccessible regardless of Private in derived class if you use Private in derived class if you use
derivation access private derivation private derivation
Protected in derived class if you use Protected in derived class if you use
protected derivation protected derivation
Protected in derived class if you use Public in derived class if you use public
public derivation derivation
int main()
{
DerivedClass1 derived_class1;
DerivedClass2 derived_class2;
derived_class1.PublicFunc();
derived_class2.PublicFunc(); // function is inaccessible
}
In DerivedClass1 , the member function PublicFunc is a public member and ProtectedFunc is a protected
member because BaseClass is a public base class. PrivateFunc is private to BaseClass , and it is inaccessible to
any derived classes.
In DerivedClass2, the functions PublicFunc and ProtectedFunc are considered private members because
BaseClass is a private base class. Again, PrivateFunc is private to BaseClass , and it is inaccessible to any
derived classes.
You can declare a derived class without a base-class access specifier. In such a case, the derivation is considered
private if the derived class declaration uses the class keyword. The derivation is considered public if the
derived class declaration uses the struct keyword. For example, the following code:
is equivalent to:
is equivalent to:
Note that members declared as having private access are not accessible to functions or derived classes unless
those functions or classes are declared using the friend declaration in the base class.
A union type cannot have a base class.
NOTE
When specifying a private base class, it is advisable to explicitly use the private keyword so users of the derived class
understand the member access.
// access_control.cpp
class Base
{
public:
int Print(); // Nonstatic member.
static int CountOf(); // Static member.
};
In the preceding code, access control prohibits conversion from a pointer to Derived2 to a pointer to Base . The
this pointer is implicitly of type Derived2 * . To select the CountOf function, this must be converted to type
Base * . Such a conversion is not permitted because Base is a private indirect base class to Derived2 .
Conversion to a private base class type is acceptable only for pointers to immediate derived classes. Therefore,
pointers of type Derived1 * can be converted to type Base * .
Note that calling the CountOf function explicitly, without using a pointer, reference, or object to select it, implies
no conversion. Therefore, the call is allowed.
Members and friends of a derived class, T , can convert a pointer to T to a pointer to a private direct base class
of T .
// access_to_virtual_functions.cpp
class VFuncBase
{
public:
virtual int GetState() { return _state; }
protected:
int _state;
};
int main()
{
VFuncDerived vfd; // Object of derived type.
VFuncBase *pvfb = &vfd; // Pointer to base type.
VFuncDerived *pvfd = &vfd; // Pointer to derived type.
int State;
In the preceding example, calling the virtual function GetState using a pointer to type VFuncBase calls
VFuncDerived::GetState , and GetState is treated as public. However, calling GetState using a pointer to type
VFuncDerived is an access-control violation because GetState is declared private in class VFuncDerived .
Cau t i on
The virtual function GetState can be called using a pointer to the base class VFuncBase . This does not mean
that the function called is the base-class version of that function.
See also
C++ Language Reference
friend (C++)
6/11/2021 • 5 minutes to read • Edit Online
In some circumstances, it is more convenient to grant member-level access to functions that are not members of
a class or to all members in a separate class. Only the class implementer can declare who its friends are. A
function or class cannot declare itself as a friend of any class. In a class definition, use the friend keyword and
the name of a non-member function or other class to grant it access to the private and protected members of
your class. In a template definition, a type parameter can be declared as a friend.
Syntax
class friend F
friend F;
Friend declarations
If you declare a friend function that was not previously declared, that function is exported to the enclosing
nonclass scope.
Functions declared in a friend declaration are treated as if they had been declared using the extern keyword.
For more information, see extern.
Although functions with global scope can be declared as friends prior to their prototypes, member functions
cannot be declared as friends before the appearance of their complete class declaration. The following code
shows why this fails:
The preceding example enters the class name ForwardDeclared into scope, but the complete declaration —
specifically, the portion that declares the function IsAFriend — is not known. Therefore, the friend declaration
in class HasFriends generates an error.
Starting in C++11, there are two forms of friend declarations for a class:
friend class F;
friend F;
The first form introduces a new class F if no existing class by that name was found in the innermost namespace.
C++11 : The second form does not introduce a new class; it can be used when the class has already been
declared, and it must be used when declaring a template type parameter or a typedef as a friend.
Use friend class F when the referenced type has not yet been declared:
namespace NS
{
class M
{
friend class F; // Introduces F but doesn't define it
};
}
namespace NS
{
class M
{
friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
};
}
In the following example, friend F refers to the F class that is declared outside the scope of NS.
class F {};
namespace NS
{
class M
{
friend F; // OK
};
}
class G
{
friend F; // OK
friend class F // Error C2371 -- redefinition
};
To declare two classes that are friends of one another, the entire second class must be specified as a friend of the
first class. The reason for this restriction is that the compiler has enough information to declare individual friend
functions only at the point where the second class is declared.
NOTE
Although the entire second class must be a friend to the first class, you can select which functions in the first class will be
friends of the second class.
friend functions
A friend function is a function that is not a member of a class but has access to the class's private and
protected members. Friend functions are not considered class members; they are normal external functions that
are given special access privileges. Friends are not in the class's scope, and they are not called using the
member-selection operators (. and -> ) unless they are members of another class. A friend function is declared
by the class that is granting access. The friend declaration can be placed anywhere in the class declaration. It is
not affected by the access control keywords.
The following example shows a Point class and a friend function, ChangePrivate . The friend function has
access to the private data member of the Point object it receives as a parameter.
// friend_functions.cpp
// compile with: /EHsc
#include <iostream>
private:
int m_i;
};
int main()
{
Point sPoint;
sPoint.PrintPrivate();
ChangePrivate(sPoint);
sPoint.PrintPrivate();
// Output: 0
1
}
class A {
public:
int Func1( B& b );
private:
int Func2( B& b );
};
class B {
private:
int _b;
In the preceding example, only the function A::Func1( B& ) is granted friend access to class B . Therefore,
access to the private member _b is correct in Func1 of class A but not in Func2 .
A friend class is a class all of whose member functions are friend functions of a class, that is, whose member
functions have access to the other class's private and protected members. Suppose the friend declaration in
class B had been:
friend class A;
In that case, all member functions in class A would have been granted friend access to class B . The following
code is an example of a friend class:
// classes_as_friends2.cpp
// compile with: /EHsc
#include <iostream>
class YourOtherClass {
public:
void change( YourClass& yc, int x ){yc.topSecret = x;}
};
int main() {
YourClass yc1;
YourOtherClass yoc1;
yc1.printMember();
yoc1.change( yc1, 5 );
yc1.printMember();
}
Friendship is not mutual unless explicitly specified as such. In the above example, member functions of
YourClass cannot access the private members of YourOtherClass .
A managed type (in C++/CLI) cannot have any friend functions, friend classes, or friend interfaces.
Friendship is not inherited, meaning that classes derived from YourOtherClass cannot access YourClass 's
private members. Friendship is not transitive, so classes that are friends of YourOtherClass cannot access
YourClass 's private members.
The following figure shows four class declarations: Base , Derived , aFriend , and anotherFriend . Only class
aFriend has direct access to the private members of Base (and to any members Base might have inherited).
See also
Keywords
private (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
private:
[member-list]
private base-class
Remarks
When preceding a list of class members, the private keyword specifies that those members are accessible only
from member functions and friends of the class. This applies to all members declared up to the next access
specifier or the end of the class.
When preceding the name of a base class, the private keyword specifies that the public and protected
members of the base class are private members of the derived class.
Default access of members in a class is private. Default access of members in a structure or union is public.
Default access of a base class is private for classes and public for structures. Unions cannot have base classes.
For related information, see friend, public, protected, and the member-access table in Controlling Access to Class
Members.
/clr Specific
In CLR types, the C++ access specifier keywords ( public , private , and protected ) can affect the visibility of
types and methods with regard to assemblies. For more information, see Member Access Control.
NOTE
Files compiled with /LN are not affected by this behavior. In this case, all managed classes (either public or private) will be
visible.
int main() {
BaseClass aBase;
DerivedClass aDerived;
DerivedClass2 aDerived2;
aBase.privMem = 1; // C2248: privMem not accessible
aDerived.privMem = 1; // C2248: privMem not accessible
// in derived class
aDerived2.pubFunc(); // C2247: pubFunc() is private in
// derived class
}
See also
Controlling Access to Class Members
Keywords
protected (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
protected:
[member-list]
protected base-class
Remarks
The protected keyword specifies access to class members in the member-list up to the next access specifier (
public or private ) or the end of the class definition. Class members declared as protected can be used only
by the following:
Member functions of the class that originally declared these members.
Friends of the class that originally declared these members.
Classes derived with public or protected access from the class that originally declared these members.
Direct privately derived classes that also have private access to protected members.
When preceding the name of a base class, the protected keyword specifies that the public and protected
members of the base class are protected members of its derived classes.
Protected members are not as private as private members, which are accessible only to members of the class
in which they are declared, but they are not as public as public members, which are accessible in any function.
Protected members that are also declared as static are accessible to any friend or member function of a
derived class. Protected members that are not declared as static are accessible to friends and member
functions in a derived class only through a pointer to, reference to, or object of the derived class.
For related information, see friend, public, private, and the member-access table in Controlling Access to Class
Members.
/clr Specific
In CLR types, the C++ access specifier keywords ( public , private , and protected ) can affect the visibility of
types and methods with regard to assemblies. For more information, see Member Access Control.
NOTE
Files compiled with /LN are not affected by this behavior. In this case, all managed classes (either public or private) will be
visible.
class Y : public X {
public:
void useProtfunc() { Protfunc(); }
} y;
int main() {
// x.m_protMemb; error, m_protMemb is protected
x.setProtMemb( 0 ); // OK, uses public access function
x.Display();
y.setProtMemb( 5 ); // OK, uses public access function
y.Display();
// x.Protfunc(); error, Protfunc() is protected
y.useProtfunc(); // OK, uses public access function
// in derived class
}
See also
Controlling Access to Class Members
Keywords
public (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
public:
[member-list]
public base-class
Remarks
When preceding a list of class members, the public keyword specifies that those members are accessible from
any function. This applies to all members declared up to the next access specifier or the end of the class.
When preceding the name of a base class, the public keyword specifies that the public and protected members
of the base class are public and protected members, respectively, of the derived class.
Default access of members in a class is private. Default access of members in a structure or union is public.
Default access of a base class is private for classes and public for structures. Unions cannot have base classes.
For more information, see private, protected, friend, and the member-access table in Controlling Access to Class
Members.
/clr Specific
In CLR types, the C++ access specifier keywords ( public , private , and protected ) can affect the visibility of
types and methods with regard to assemblies. For more information, see Member Access Control.
NOTE
Files compiled with /LN are not affected by this behavior. In this case, all managed classes (either public or private) will be
visible.
int main() {
BaseClass aBase;
DerivedClass aDerived;
aBase.pubFunc(); // pubFunc() is accessible
// from any function
aDerived.pubFunc(); // pubFunc() is still public in
// derived class
}
See also
Controlling Access to Class Members
Keywords
Brace initialization
11/2/2020 • 3 minutes to read • Edit Online
It is not always necessary to define a constructor for a class, especially ones that are relatively simple. Users can
initialize objects of a class or struct by using uniform initialization, as shown in the following example:
// no_constructor.cpp
// Compile with: cl /EHsc no_constructor.cpp
#include <time.h>
// No constructor
struct TempData
{
int StationId;
time_t timeSet;
double current;
double maxTemp;
double minTemp;
};
// Has a constructor
struct TempData2
{
TempData2(double minimum, double maximum, double cur, int id, time_t t) :
stationId{id}, timeSet{t}, current{cur}, maxTemp{maximum}, minTemp{minimum} {}
int stationId;
time_t timeSet;
double current;
double maxTemp;
double minTemp;
};
int main()
{
time_t time_to_set;
return 0;
}
Note that when a class or struct has no constructor, you provide the list elements in the order that the members
are declared in the class. If the class has a constructor, provide the elements in the order of the parameters. If a
type has a default constructor, either implicitly or explicitly declared, you can use default brace initialization (with
empty braces). For example, the following class may be initialized by using both default and non-default brace
initialization:
#include <string>
using namespace std;
class class_a {
public:
class_a() {}
class_a(string str) : m_string{ str } {}
class_a(string str, double dbl) : m_string{ str }, m_double{ dbl } {}
double m_double;
string m_string;
};
int main()
{
class_a c1{};
class_a c1_1;
If a class has non-default constructors, the order in which class members appear in the brace initializer is the
order in which the corresponding parameters appear in the constructor, not the order in which the members are
declared (as with class_a in the previous example). Otherwise, if the type has no declared constructor, the
order in which the members appear in the brace initializer is the same as the order in which they are declared; in
this case, you can initialize as many of the public members as you wish, but you cannot skip any member. The
following example shows the order that's used in brace initialization when there is no declared constructor:
class class_d {
public:
float m_float;
string m_string;
wchar_t m_char;
};
int main()
{
class_d d1{};
class_d d1{ 4.5 };
class_d d2{ 4.5, "string" };
class_d d3{ 4.5, "string", 'c' };
If the default constructor is explicitly declared but marked as deleted, default brace initialization cannot be used:
class class_f {
public:
class_f() = delete;
class_f(string x): m_string { x } {}
string m_string;
};
int main()
{
class_f cf{ "hello" };
class_f cf1{}; // compiler error C2280: attempting to reference a deleted function
}
You can use brace initialization anywhere you would typically do initialization—for example, as a function
parameter or a return value, or with the new keyword:
In /std:c++17 mode, the rules for empty brace initialization are slightly more restrictive. See Derived
constructors and extended aggregate initialization.
initializer_list constructors
The initializer_list Class represents a list of objects of a specified type that can be used in a constructor, and in
other contexts. You can construct an initializer_list by using brace initialization:
IMPORTANT
To use this class, you must include the <initializer_list> header.
An initializer_list can be copied. In this case, the members of the new list are references to the members of
the original list:
initializer_list<int> ilist1{ 5, 6, 7 };
initializer_list<int> ilist2( ilist1 );
if (ilist1.begin() == ilist2.begin())
cout << "yes" << endl; // expect "yes"
The standard library container classes, and also string , wstring , and regex , have initializer_list
constructors. The following examples show how to do brace initialization with these constructors:
See also
Classes and Structs
Constructors
Object lifetime and resource management (RAII)
3/19/2020 • 3 minutes to read • Edit Online
Unlike managed languages, C++ doesn't have automatic garbage collection. That's an internal process that
releases heap memory and other resources as a program runs. A C++ program is responsible for returning all
acquired resources to the operating system. Failure to release an unused resource is called a leak. Leaked
resources are unavailable to other programs until the process exits. Memory leaks in particular are a common
cause of bugs in C-style programming.
Modern C++ avoids using heap memory as much as possible by declaring objects on the stack. When a
resource is too large for the stack, then it should be owned by an object. As the object gets initialized, it acquires
the resource it owns. The object is then responsible for releasing the resource in its destructor. The owning
object itself is declared on the stack. The principle that objects own resources is also known as "resource
acquisition is initialization," or RAII.
When a resource-owning stack object goes out of scope, its destructor is automatically invoked. In this way,
garbage collection in C++ is closely related to object lifetime, and is deterministic. A resource is always released
at a known point in the program, which you can control. Only deterministic destructors like those in C++ can
handle memory and non-memory resources equally.
The following example shows a simple object w . It's declared on the stack at function scope, and is destroyed at
the end of the function block. The object w owns no resources (such as heap-allocated memory). Its only
member g is itself declared on the stack, and simply goes out of scope along with w . No special code is
needed in the widget destructor.
class widget {
private:
gadget g; // lifetime automatically tied to enclosing object
public:
void draw();
};
void functionUsingWidget () {
widget w; // lifetime automatically tied to enclosing scope
// constructs w, including the w.g gadget member
// ...
w.draw();
// ...
} // automatic destruction and deallocation for w and w.g
// automatic exception safety,
// as if "finally { w.dispose(); w.g.dispose(); }"
In the following example, w owns a memory resource and so must have code in its destructor to delete the
memory.
class widget
{
private:
int* data;
public:
widget(const int size) { data = new int[size]; } // acquire
~widget() { delete[] data; } // release
void do_something() {}
};
void functionUsingWidget() {
widget w(1000000); // lifetime automatically tied to enclosing scope
// constructs w, including the w.data member
w.do_something();
Since C++11, there's a better way to write the previous example: by using a smart pointer from the standard
library. The smart pointer handles the allocation and deletion of the memory it owns. Using a smart pointer
eliminates the need for an explicit destructor in the widget class.
#include <memory>
class widget
{
private:
std::unique_ptr<int> data;
public:
widget(const int size) { data = std::make_unique<int>(size); }
void do_something() {}
};
void functionUsingWidget() {
widget w(1000000); // lifetime automatically tied to enclosing scope
// constructs w, including the w.data gadget member
// ...
w.do_something();
// ...
} // automatic destruction and deallocation for w and w.data
By using smart pointers for memory allocation, you may eliminate the potential for memory leaks. This model
works for other resources, such as file handles or sockets. You can manage your own resources in a similar way
in your classes. For more information, see Smart pointers.
The design of C++ ensures objects are destroyed when they go out of scope. That is, they get destroyed as
blocks are exited, in reverse order of construction. When an object is destroyed, its bases and members are
destroyed in a particular order. Objects declared outside of any block, at global scope, can lead to problems. It
may be difficult to debug, if the constructor of a global object throws an exception.
See also
Welcome back to C++
C++ Language Reference
C++ Standard Library
Pimpl For Compile-Time Encapsulation (Modern
C++)
3/6/2021 • 2 minutes to read • Edit Online
The pimpl idiom is a modern C++ technique to hide implementation, to minimize coupling, and to separate
interfaces. Pimpl is short for "pointer to implementation." You may already be familiar with the concept but
know it by other names like Cheshire Cat or Compiler Firewall idiom.
Pimpl header
// my_class.h
class my_class {
// ... all public and protected stuff goes here ...
private:
class impl; unique_ptr<impl> pimpl; // opaque type here
};
The pimpl idiom avoids rebuild cascades and brittle object layouts. It's well suited for (transitively) popular types.
Pimpl implementation
Define the impl class in the .cpp file.
// my_class.cpp
class my_class::impl { // defined privately here
// ... all private data and functions: all of these
// can now change without recompiling callers ...
};
my_class::my_class(): pimpl( new impl )
{
// ... set impl values ...
}
Best practices
Consider whether to add support for non-throwing swap specialization.
See also
Welcome back to C++
C++ Language Reference
C++ Standard Library
Portability at ABI boundaries
11/21/2019 • 2 minutes to read • Edit Online
Use sufficiently portable types and conventions at binary interface boundaries. A "portable type" is a C built-in
type or a struct that contains only C built-in types. Class types can only be used when caller and callee agree on
layout, calling convention, etc. That's only possible when both are compiled with the same compiler and
compiler settings.
// class widget {
// widget();
// ~widget();
// double method( int, gadget& );
// };
extern "C" { // functions using explicit "this"
struct widget; // opaque type (forward declaration only)
widget* STDCALL widget_create(); // constructor creates new "this"
void STDCALL widget_destroy(widget*); // destructor consumes "this"
double STDCALL widget_method(widget*, int, gadget*); // method uses "this"
}
See also
Welcome back to C++
C++ Language Reference
C++ Standard Library
Constructors (C++)
3/6/2021 • 17 minutes to read • Edit Online
To customize how class members are initialized, or to invoke functions when an object of your class is created,
define a constructor. A constructor has the same name as the class and no return value. You can define as many
overloaded constructors as needed to customize initialization in various ways. Typically, constructors have public
accessibility so that code outside the class definition or inheritance hierarchy can create objects of the class. But
you can also declare a constructor as protected or private .
Constructors can optionally take a member init list. This is a more efficient way to initialize class members than
assigning values in the constructor body. The following example shows a class Box with three overloaded
constructors. The last two use member init lists:
class Box {
public:
// Default constructor
Box() {}
private:
// Will have value of 0 when default constructor is called.
// If we didn't zero-init here, default constructor would
// leave them uninitialized with garbage values.
int m_width{ 0 };
int m_length{ 0 };
int m_height{ 0 };
};
When you declare an instance of a class, the compiler chooses which constructor to invoke based on the rules of
overload resolution:
int main()
{
Box b; // Calls Box()
The identifier must refer to a class member; it is initialized with the value of the argument. The argument can be
one of the constructor parameters, a function call or a std::initializer_list<T>.
const members and members of reference type must be initialized in the member initializer list.
Calls to parameterized base class constructors should be made in the initializer list to ensure the base class is
fully initialized prior to execution of the derived constructor.
Default constructors
Default constructors typically have no parameters, but they can have parameters with default values.
class Box {
public:
Box() { /*perform any required default initialization steps*/}
Default constructors are one of the special member functions. If no constructors are declared in a class, the
compiler provides an implicit inline default constructor.
#include <iostream>
using namespace std;
class Box {
public:
int Volume() {return m_width * m_height * m_length;}
private:
int m_width { 0 };
int m_height { 0 };
int m_length { 0 };
};
int main() {
Box box1; // Invoke compiler-generated constructor
cout << "box1.Volume: " << box1.Volume() << endl; // Outputs 0
}
If you rely on an implicit default constructor, be sure to initialize members in the class definition, as shown in the
previous example. Without those initializers, the members would be uninitialized and the Volume() call would
produce a garbage value. In general, it is good practice to initialize members in this way even when not relying
on an implicit default constructor.
You can prevent the compiler from generating an implicit default constructor by defining it as deleted:
// Default constructor
Box() = delete;
A compiler-generated default constructor will be defined as deleted if any class members are not default-
constructible. For example, all members of class type, and their class-type members, must have a default
constructor and destructors that are accessible. All data members of reference type, as well as const members
must have a default member initializer.
When you call a compiler-generated default constructor and try to use parentheses, a warning is issued:
class myclass{};
int main(){
myclass mc(); // warning C4930: prototyped function not called (was a variable definition intended?)
}
This is an example of the Most Vexing Parse problem. Because the example expression can be interpreted either
as the declaration of a function or as the invocation of a default constructor, and because C++ parsers favor
declarations over other things, the expression is treated as a function declaration. For more information, see
Most Vexing Parse.
If any non-default constructors are declared, the compiler does not provide a default constructor:
class Box {
public:
Box(int width, int length, int height)
: m_width(width), m_length(length), m_height(height){}
private:
int m_width;
int m_length;
int m_height;
};
int main(){
If a class has no default constructor, an array of objects of that class cannot be constructed by using square-
bracket syntax alone. For example, given the previous code block, an array of Boxes cannot be declared like this:
However, you can use a set of initializer lists to initialize an array of Box objects:
Box boxes[3]{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
For more information, see Initializers.
Copy constructors
A copy constructor initializes an object by copying the member values from an object of the same type. If your
class members are all simple types such as scalar values, the compiler-generated copy constructor is sufficient
and you do not need to define your own. If your class requires more complex initialization, then you need to
implement a custom copy constructor. For example, if a class member is a pointer then you need to define a
copy constructor to allocate new memory and copy the values from the other's pointed-to object. The compiler-
generated copy constructor simply copies the pointer, so that the new pointer still points to the other's memory
location.
A copy constructor may have one of these signatures:
When you define a copy constructor, you should also define a copy assignment operator (=). For more
information, see Assignment and Copy constructors and copy assignment operators.
You can prevent your object from being copied by defining the copy constructor as deleted:
Attempting to copy the object produces error C2280: attempting to reference a deleted function.
Move constructors
A move constructor is a special member function that moves ownership of an existing object's data to a new
variable without copying the original data. It takes an rvalue reference as its first parameter, and any additional
parameters must have default values. Move constructors can significantly increase your program's efficiency
when passing around large objects.
Box(Box&& other);
The compiler chooses a move constructor in certain situations where the object is being initialized by another
object of the same type that is about to be destroyed and no longer needs its resources. The following example
shows one case when a move constructor is selected by overload resolution. In the constructor that calls
get_Box() , the returned value is an xvalue (eXpiring value). It is not assigned to any variable and is therefore
about to go out of scope. To provide motivation for this example, let's give Box a large vector of strings that
represent its contents. Rather than copying the vector and its strings, the move constructor "steals" it from the
expiring value "box" so that the vector now belongs to the new object. The call to std::move is all that's needed
because both vector and string classes implement their own move constructors.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class Box {
public:
Box() { std::cout << "default" << std::endl; }
Box(int width, int height, int length)
: m_width(width), m_height(height), m_length(length)
{
std::cout << "int,int,int" << std::endl;
}
Box(Box& other)
: m_width(other.m_width), m_height(other.m_height), m_length(other.m_length)
{
std::cout << "copy" << std::endl;
}
Box(Box&& other) : m_width(other.m_width), m_height(other.m_height), m_length(other.m_length)
{
m_contents = std::move(other.m_contents);
std::cout << "move" << std::endl;
}
int Volume() { return m_width * m_height * m_length; }
void Add_Item(string item) { m_contents.push_back(item); }
void Print_Contents()
{
for (const auto& item : m_contents)
{
cout << item << " ";
}
}
private:
int m_width{ 0 };
int m_height{ 0 };
int m_length{ 0 };
vector<string> m_contents;
};
Box get_Box()
{
Box b(5, 10, 18); // "int,int,int"
b.Add_Item("Toupee");
b.Add_Item("Megaphone");
b.Add_Item("Suit");
return b;
}
int main()
{
Box b; // "default"
Box b1(b); // "copy"
Box b2(get_Box()); // "move"
cout << "b2 contents: ";
b2.Print_Contents(); // Prove that we have all the values
char ch;
cin >> ch; // keep window open
return 0;
}
If a class does not define a move constructor, the compiler generates an implicit one if there is no user-declared
copy constructor, copy assignment operator, move assignment operator, or destructor. If no explicit or implicit
move constructor is defined, operations that would otherwise use a move constructor use the copy constructor
instead. If a class declares a move constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted.
An implicitly declared move constructor is defined as deleted if any members that are class types lack a
destructor or the compiler cannot determine which constructor to use for the move operation.
For more information about how to write a non-trivial move constructor, see Move Constructors and Move
Assignment Operators (C++).
class Box
{
public:
Box2() = delete;
Box2(const Box2& other) = default;
Box2& operator=(const Box2& other) = default;
Box2(Box2&& other) = default;
Box2& operator=(Box2&& other) = default;
//...
};
constexpr constructors
A constructor may be declared as constexpr if
it is either declared as defaulted or else it satisfies all the conditions for constexpr functions in general;
the class has no virtual base classes;
each of the parameters is a literal type;
the body is not a function try-block;
all non-static data members and base class sub-objects are initialized;
if the class is (a) a union having variant members, or (b) has anonymous unions, only one of the union
members is initialized;
every non-static data member of class type, and all base-class sub-objects have a constexpr constructor
Explicit constructors
If a class has a constructor with a single parameter, or if all parameters except one have a default value, the
parameter type can be implicitly converted to the class type. For example, if the Box class has a constructor like
this:
Box b = 42;
class ShippingOrder
{
public:
ShippingOrder(Box b, double postage) : m_box(b), m_postage(postage){}
private:
Box m_box;
double m_postage;
}
//elsewhere...
ShippingOrder so(42, 10.8);
Such conversions can be useful in some cases, but more often they can lead to subtle but serious errors in your
code. As a general rule, you should use the explicit keyword on a constructor (and user-defined operators) to
prevent this kind of implicit type conversion:
When the constructor is explicit, this line causes a compiler error: ShippingOrder so(42, 10.8); . For more
information, see User-Defined Type Conversions.
Order of construction
A constructor performs its work in this order:
1. It calls base class and member constructors in the order of declaration.
2. If the class is derived from virtual base classes, it initializes the object's virtual base pointers.
3. If the class has or inherits virtual functions, it initializes the object's virtual function pointers. Virtual
function pointers point to the class's virtual function table to enable correct binding of virtual function
calls to code.
4. It executes any code in its function body.
The following example shows the order in which base class and member constructors are called in the
constructor for a derived class. First, the base constructor is called, then the base-class members are initialized in
the order in which they appear in the class declaration, and then the derived constructor is called.
#include <iostream>
class Contained1 {
public:
Contained1() { cout << "Contained1 ctor\n"; }
};
class Contained2 {
public:
Contained2() { cout << "Contained2 ctor\n"; }
};
class Contained3 {
public:
Contained3() { cout << "Contained3 ctor\n"; }
};
class BaseContainer {
public:
BaseContainer() { cout << "BaseContainer ctor\n"; }
private:
Contained1 c1;
Contained2 c2;
};
int main() {
DerivedContainer dc;
}
Contained1 ctor
Contained2 ctor
BaseContainer ctor
Contained3 ctor
DerivedContainer ctor
A derived class constructor always calls a base class constructor, so that it can rely on completely constructed
base classes before any extra work is done. The base class constructors are called in order of derivation—for
example, if ClassA is derived from ClassB , which is derived from ClassC , the ClassC constructor is called
first, then the ClassB constructor, then the ClassA constructor.
If a base class does not have a default constructor, you must supply the base class constructor parameters in the
derived class constructor:
class Box {
public:
Box(int width, int length, int height){
m_width = width;
m_length = length;
m_height = height;
}
private:
int m_width;
int m_length;
int m_height;
};
int main(){
If a constructor throws an exception, the order of destruction is the reverse of the order of construction:
1. The code in the body of the constructor function is unwound.
2. Base class and member objects are destroyed, in the reverse order of declaration.
3. If the constructor is non-delegating, all fully-constructed base class objects and members are destroyed.
However, because the object itself is not fully constructed, the destructor is not run.
struct Derived;
struct Base {
friend struct Derived;
private:
Base() {}
};
In C++17, Derived is now considered an aggregate type. It means that the initialization of Base via the private
default constructor happens directly, as part of the extended aggregate initialization rule. Previously, the Base
private constructor was called via the Derived constructor, and it succeeded because of the friend declaration.
The following example shows C++17 behavior in Visual Studio 2017 and later in /std:c++17 mode:
struct Derived;
struct Base {
friend struct Derived;
private:
Base() {}
};
#include <iostream>
using namespace std;
class BaseClass1 {
public:
BaseClass1() { cout << "BaseClass1 ctor\n"; }
};
class BaseClass2 {
public:
BaseClass2() { cout << "BaseClass2 ctor\n"; }
};
class BaseClass3 {
public:
BaseClass3() { cout << "BaseClass3 ctor\n"; }
};
class DerivedClass : public BaseClass1,
public BaseClass2,
public BaseClass3
{
public:
DerivedClass() { cout << "DerivedClass ctor\n"; }
};
int main() {
DerivedClass dc;
}
BaseClass1 ctor
BaseClass2 ctor
BaseClass3 ctor
DerivedClass ctor
Delegating constructors
A delegating constructor calls a different constructor in the same class to do some of the work of initialization.
This is useful when you have multiple constructors that all have to perform similar work. You can write the main
logic in one constructor and invoke it from others. In the following trivial example, Box(int) delegates its work to
Box(int,int,int):
class Box {
public:
// Default constructor
Box() {}
The object created by the constructors is fully initialized as soon as any constructor is finished. For more
information, see Delegating Constructors.
class Base
{
public:
Base() { cout << "Base()" << endl; }
Base(const Base& other) { cout << "Base(Base&)" << endl; }
explicit Base(int i) : num(i) { cout << "Base(int)" << endl; }
explicit Base(char c) : letter(c) { cout << "Base(char)" << endl; }
private:
int num;
char letter;
};
private:
// Can't initialize newMember from Base constructors.
int newMember{ 0 };
};
int main()
{
cout << "Derived d1(5) calls: ";
Derived d1(5);
cout << "Derived d1('c') calls: ";
Derived d2('c');
cout << "Derived d3 = d2 calls: " ;
Derived d3 = d2;
cout << "Derived d4 calls: ";
Derived d4;
}
/* Output:
Derived d1(5) calls: Base(int)
Derived d1('c') calls: Base(char)
Derived d3 = d2 calls: Base(Base&)
Derived d4 calls: Base()*/
Visual Studio 2017 and later : The using statement in /std:c++17 mode brings into scope all constructors
from the base class except those that have an identical signature to constructors in the derived class. In general,
it is best to use inheriting constructors when the derived class declares no new data members or constructors.
A class template can inherit all the constructors from a type argument if that type specifies a base class:
A deriving class cannot inherit from multiple base classes if those base classes have constructors that have an
identical signature.
class Label {
public:
Label(const string& name, const string& address) { m_name = name; m_address = address; }
string m_name;
string m_address;
};
int main(){
// passing a named Label
Label label1{ "some_name", "some_address" };
StorageBox sb1(1, 2, 3, label1);
In this section
Copy constructors and copy assignment operators
Move constructors and move assignment operators
Delegating constructors
See also
Classes and structs
Copy Constructors and Copy Assignment Operators
(C++)
3/6/2021 • 3 minutes to read • Edit Online
NOTE
Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment. In
this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move
assignment, see Move Constructors and Move Assignment Operators (C++).
Both the assignment operation and the initialization operation cause objects to be copied.
Assignment : When one object's value is assigned to another object, the first object is copied to the
second object. Therefore,
Point a, b;
...
a = b;
TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;
The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore
FILE2.DAT and make b a second handle to FILE1.DAT." You must attach appropriate copying semantics to each
class, as follows.
By using the assignment operator operator= together with a reference to the class type as the return
type and the parameter that is passed by const reference—for example
ClassName& operator=(const ClassName& x); .
int main()
{
}
NOTE
Make the type of the copy constructor's argument const class-name& whenever possible. This prevents the copy
constructor from accidentally changing the object from which it is copying. It also enables copying from const objects.
NOTE
When virtual base classes are initialized by copy constructors, compiler-generated or user-defined, they are initialized only
once: at the point when they are constructed.
The implications are similar to those of the copy constructor. When the argument type is not const , assignment
from a const object generates an error. The reverse is not true: If a const value is assigned to a value that is
not const , the assignment succeeds.
For more information about overloaded assignment operators, see Assignment.
Move Constructors and Move Assignment
Operators (C++)
3/6/2021 • 6 minutes to read • Edit Online
This topic describes how to write a move constructor and a move assignment operator for a C++ class. A move
constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For
more information about move semantics, see Rvalue Reference Declarator: &&.
This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.
// MemoryBlock.h
#pragma once
#include <iostream>
#include <algorithm>
class MemoryBlock
{
public:
// Destructor.
~MemoryBlock()
{
std::cout << "In ~MemoryBlock(). length = "
<< _length << ".";
if (_data != nullptr)
{
std::cout << " Deleting resource.";
// Delete the resource.
delete[] _data;
}
// Copy constructor.
MemoryBlock(const MemoryBlock& other)
: _length(other._length)
, _data(new int[other._length])
{
std::cout << "In MemoryBlock(const MemoryBlock&). length = "
<< other._length << ". Copying resource." << std::endl;
_length = other._length;
_data = new int[_length];
std::copy(other._data, other._data + _length, _data);
}
return *this;
}
private:
size_t _length; // The length of the resource.
int* _data; // The resource.
};
The following procedures describe how to write a move constructor and a move assignment operator for the
example C++ class.
To create a move constructor for a C++ class
1. Define an empty constructor method that takes an rvalue reference to the class type as its parameter, as
demonstrated in the following example:
MemoryBlock(MemoryBlock&& other)
: _data(nullptr)
, _length(0)
{
}
2. In the move constructor, assign the class data members from the source object to the object that is being
constructed:
_data = other._data;
_length = other._length;
3. Assign the data members of the source object to default values. This prevents the destructor from freeing
resources (such as memory) multiple times:
other._data = nullptr;
other._length = 0;
if (this != &other)
{
}
3. In the conditional statement, free any resources (such as memory) from the object that is being assigned
to.
The following example frees the _data member from the object that is being assigned to:
Follow steps 2 and 3 in the first procedure to transfer the data members from the source object to the
object that is being constructed:
return *this;
if (this != &other)
{
// Free the existing resource.
delete[] _data;
int main()
{
// Create a vector object and add a few elements to it.
vector<MemoryBlock> v;
v.push_back(MemoryBlock(25));
v.push_back(MemoryBlock(75));
Before Visual Studio 2010, this example produced the following output:
The version of this example that uses move semantics is more efficient than the version that does not use move
semantics because it performs fewer copy, memory allocation, and memory deallocation operations.
Robust Programming
To prevent resource leaks, always free resources (such as memory, file handles, and sockets) in the move
assignment operator.
To prevent the unrecoverable destruction of resources, properly handle self-assignment in the move assignment
operator.
If you provide both a move constructor and a move assignment operator for your class, you can eliminate
redundant code by writing the move constructor to call the move assignment operator. The following example
shows a revised version of the move constructor that calls the move assignment operator:
// Move constructor.
MemoryBlock(MemoryBlock&& other) noexcept
: _data(nullptr)
, _length(0)
{
*this = std::move(other);
}
See also
Rvalue Reference Declarator: &&
std::move
Delegating constructors
3/27/2020 • 2 minutes to read • Edit Online
Many classes have multiple constructors that do similar things—for example, validate parameters:
class class_c {
public:
int max;
int min;
int middle;
class_c() {}
class_c(int my_max) {
max = my_max > 0 ? my_max : 10;
}
class_c(int my_max, int my_min) {
max = my_max > 0 ? my_max : 10;
min = my_min > 0 && my_min < max ? my_min : 1;
}
class_c(int my_max, int my_min, int my_middle) {
max = my_max > 0 ? my_max : 10;
min = my_min > 0 && my_min < max ? my_min : 1;
middle = my_middle < max && my_middle > min ? my_middle : 5;
}
};
You could reduce the repetitive code by adding a function that does all of the validation, but the code for
class_c would be easier to understand and maintain if one constructor could delegate some of the work to
another one. To add delegating constructors, use the constructor (. . .) : constructor (. . .) syntax:
class class_c {
public:
int max;
int min;
int middle;
class_c(int my_max) {
max = my_max > 0 ? my_max : 10;
}
class_c(int my_max, int my_min) : class_c(my_max) {
min = my_min > 0 && my_min < max ? my_min : 1;
}
class_c(int my_max, int my_min, int my_middle) : class_c (my_max, my_min){
middle = my_middle < max && my_middle > min ? my_middle : 5;
}
};
int main() {
class_c c1{ 1, 3, 2 };
}
As you step through the previous example, notice that the constructor class_c(int, int, int) first calls the
constructor class_c(int, int) , which in turn calls class_c(int) . Each of the constructors performs only the
work that is not performed by the other constructors.
The first constructor that's called initializes the object so that all of its members are initialized at that point. You
can’t do member initialization in a constructor that delegates to another constructor, as shown here:
class class_a {
public:
class_a() {}
// member initialization here, no delegate
class_a(string str) : m_string{ str } {}
The next example shows the use of non-static data-member initializers. Notice that if a constructor also
initializes a given data member, the member initializer is overridden:
class class_a {
public:
class_a() {}
class_a(string str) : m_string{ str } {}
class_a(string str, double dbl) : class_a(str) { m_double = dbl; }
double m_double{ 1.0 };
string m_string{ m_double < 10.0 ? "alpha" : "beta" };
};
int main() {
class_a a{ "hello", 2.0 }; //expect a.m_double == 2.0, a.m_string == "hello"
int y = 4;
}
The constructor delegation syntax doesn't prevent the accidental creation of constructor recursion—
Constructor1 calls Constructor2 which calls Constructor1—and no errors are thrown until there is a stack
overflow. It's your responsibility to avoid cycles.
class class_f{
public:
int max;
int min;
// don't do this
class_f() : class_f(6, 3){ }
class_f(int my_max, int my_min) : class_f() { }
};
Destructors (C++)
3/6/2021 • 7 minutes to read • Edit Online
A destructor is a member function that is invoked automatically when the object goes out of scope or is
explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ).
For example, the destructor for class String is declared: ~String() .
If you do not define a destructor, the compiler will provide a default one; for many classes this is sufficient. You
only need to define a custom destructor when the class stores handles to system resources that need to be
released, or pointers that own the memory they point to.
Consider the following declaration of a String class:
// spec1_destructors.cpp
#include <string>
class String {
public:
String( char *ch ); // Declare constructor
~String(); // and destructor.
private:
char *_text;
size_t sizeOfText;
};
int main() {
String str("The piper in the glen...");
}
In the preceding example, the destructor String::~String uses the delete operator to deallocate the space
dynamically allocated for text storage.
Declaring destructors
Destructors are functions with the same name as the class but preceded by a tilde ( ~ )
Several rules govern the declaration of destructors. Destructors:
Do not accept arguments.
Do not return a value (or void ).
Cannot be declared as const , volatile , or static . However, they can be invoked for the destruction of
objects declared as const , volatile , or static .
Can be declared as virtual . Using virtual destructors, you can destroy objects without knowing their
type — the correct destructor for the object is invoked using the virtual function mechanism. Note that
destructors can also be declared as pure virtual functions for abstract classes.
Using destructors
Destructors are called when one of the following events occurs:
A local (automatic) object with block scope goes out of scope.
An object allocated using the new operator is explicitly deallocated using delete .
The lifetime of a temporary object ends.
A program ends and global or static objects exist.
The destructor is explicitly called using the destructor function's fully qualified name.
Destructors can freely call class member functions and access class member data.
There are two restrictions on the use of destructors:
You cannot take its address.
Derived classes do not inherit the destructor of their base class.
Order of destruction
When an object goes out of scope or is deleted, the sequence of events in its complete destruction is as follows:
1. The class's destructor is called, and the body of the destructor function is executed.
2. Destructors for nonstatic member objects are called in the reverse order in which they appear in the class
declaration. The optional member initialization list used in construction of these members does not affect
the order of construction or destruction.
3. Destructors for non-virtual base classes are called in the reverse order of declaration.
4. Destructors for virtual base classes are called in the reverse order of declaration.
// order_of_destruction.cpp
#include <cstdio>
int main() {
A1 * a = new A3;
delete a;
printf("\n");
B1 * b = new B3;
delete b;
printf("\n");
B3 * b2 = new B3;
delete b2;
}
Output: A3 dtor
A2 dtor
A1 dtor
B1 dtor
B3 dtor
B2 dtor
B1 dtor
class A
class B
class C : virtual public A, virtual public B
class D : virtual public A, virtual public B
class E : public C, public D, virtual public B
To determine the order of destruction of the virtual base classes of an object of type E , the compiler builds a list
by applying the following algorithm:
1. Traverse the graph left, starting at the deepest point in the graph (in this case, E ).
2. Perform leftward traversals until all nodes have been visited. Note the name of the current node.
3. Revisit the previous node (down and to the right) to find out whether the node being remembered is a
virtual base class.
4. If the remembered node is a virtual base class, scan the list to see whether it has already been entered. If
it is not a virtual base class, ignore it.
5. If the remembered node is not yet in the list, add it to the bottom of the list.
6. Traverse the graph up and along the next path to the right.
7. Go to step 2.
8. When the last upward path is exhausted, note the name of the current node.
9. Go to step 3.
10. Continue this process until the bottom node is again the current node.
Therefore, for class E , the order of destruction is:
1. The non-virtual base class E .
2. The non-virtual base class D .
3. The non-virtual base class C .
4. The virtual base class B .
5. The virtual base class A .
This process produces an ordered list of unique entries. No class name appears twice. Once the list is
constructed, it is walked in reverse order, and the destructor for each of the classes in the list from the last to the
first is called.
The order of construction or destruction is primarily important when constructors or destructors in one class
rely on the other component being created first or persisting longer — for example, if the destructor for A (in
the figure shown above) relied on B still being present when its code executed, or vice versa.
Such interdependencies between classes in an inheritance graph are inherently dangerous because classes
derived later can alter which is the leftmost path, thereby changing the order of construction and destruction.
Non-virtual base classes
The destructors for non-virtual base classes are called in the reverse order in which the base class names are
declared. Consider the following class declaration:
In the preceding example, the destructor for Base2 is called before the destructor for Base1 .
The notation for explicit calls to destructors, shown in the preceding, can be used regardless of whether the type
defines a destructor. This allows you to make such explicit calls without knowing if a destructor is defined for the
type. An explicit call to a destructor where none is defined has no effect.
Robust programming
A class needs a destructor if it acquires a resource, and to manage the resource safely it probably has to
implement a copy constructor and a copy assignment.
If these special functions are not defined by the user, they are implicitly defined by the compiler. The implicitly
generated constructors and assignment operators perform shallow, memberwise copy, which is almost certainly
wrong if an object is managing a resource.
In the next example, the implicitly generated copy constructor will make the pointers str1.text and str2.text
refer to the same memory, and when we return from copy_strings() , that memory will be deleted twice, which
is undefined behavior:
void copy_strings()
{
String str1("I have a sense of impending disaster...");
String str2 = str1; // str1.text and str2.text now refer to the same object
} // delete[] _text; deallocates the same memory twice
// undefined behavior
Explicitly defining a destructor, copy constructor, or copy assignment operator prevents implicit definition of the
move constructor and the move assignment operator. In this case, failing to provide move operations is usually,
if copying is expensive, a missed optimization opportunity.
See also
Copy Constructors and Copy Assignment Operators
Move Constructors and Move Assignment Operators
Overview of Member Functions
3/6/2021 • 2 minutes to read • Edit Online
Member functions are either static or nonstatic. The behavior of static member functions differs from other
member functions because static member functions have no implicit this argument. Nonstatic member
functions have a this pointer. Member functions, whether static or nonstatic, can be defined either in or
outside the class declaration.
If a member function is defined inside a class declaration, it is treated as an inline function, and there is no need
to qualify the function name with its class name. Although functions defined inside class declarations are already
treated as inline functions, you can use the inline keyword to document code.
An example of declaring a function within a class declaration follows:
// overview_of_member_functions1.cpp
class Account
{
public:
// Declare the member function Deposit within the declaration
// of class Account.
double Deposit( double HowMuch )
{
balance += HowMuch;
return balance;
}
private:
double balance;
};
int main()
{
}
If a member function's definition is outside the class declaration, it is treated as an inline function only if it is
explicitly declared as inline . In addition, the function name in the definition must be qualified with its class
name using the scope-resolution operator ( :: ).
The following example is identical to the previous declaration of class Account , except that the Deposit
function is defined outside the class declaration:
// overview_of_member_functions2.cpp
class Account
{
public:
// Declare the member function Deposit but do not define it.
double Deposit( double HowMuch );
private:
double balance;
};
int main()
{
}
NOTE
Although member functions can be defined either inside a class declaration or separately, no member functions can be
added to a class after the class is defined.
Classes containing member functions can have many declarations, but the member functions themselves must
have only one definition in a program. Multiple definitions cause an error message at link time. If a class
contains inline function definitions, the function definitions must be identical to observe this "one definition"
rule.
virtual Specifier
3/6/2021 • 2 minutes to read • Edit Online
The virtual keyword can be applied only to nonstatic class member functions. It signifies that binding of calls to
the function is deferred until run time. For more information, see Virtual Functions.
override Specifier
3/6/2021 • 2 minutes to read • Edit Online
You can use the override keyword to designate member functions that override a virtual function in a base
class.
Syntax
function-declaration override;
Remarks
override is context-sensitive and has special meaning only when it's used after a member function declaration;
otherwise, it's not a reserved keyword.
Example
Use override to help prevent inadvertent inheritance behavior in your code. The following example shows
where, without using override , the member function behavior of the derived class may not have been intended.
The compiler doesn't emit any errors for this code.
class BaseClass
{
virtual void funcA();
virtual void funcB() const;
virtual void funcC(int = 0);
void funcD();
};
When you use override , the compiler generates errors instead of silently creating new member functions.
class BaseClass
{
virtual void funcA();
virtual void funcB() const;
virtual void funcC(int = 0);
void funcD();
};
To specify that functions cannot be overridden and that classes cannot be inherited, use the final keyword.
See also
final Specifier
Keywords
final Specifier
3/6/2021 • 2 minutes to read • Edit Online
You can use the final keyword to designate virtual functions that cannot be overridden in a derived class. You
can also use it to designate classes that cannot be inherited.
Syntax
function-declaration final;
class class-name final base-classes
Remarks
final is context-sensitive and has special meaning only when it's used after a function declaration or class name;
otherwise, it's not a reserved keyword.
When final is used in class declarations, base-classes is an optional part of the declaration.
Example
The following example uses the final keyword to specify that a virtual function cannot be overridden.
class BaseClass
{
virtual void func() final;
};
For information about how to specify that member functions can be overridden, see override Specifier.
The next example uses the final keyword to specify that a class cannot be inherited.
See also
Keywords
override Specifier
Inheritance (C++)
4/30/2021 • 2 minutes to read • Edit Online
This section explains how to use derived classes to produce extensible programs.
Overview
New classes can be derived from existing classes using a mechanism called "inheritance" (see the information
beginning in Single Inheritance). Classes that are used for derivation are called "base classes" of a particular
derived class. A derived class is declared using the following syntax:
After the tag (name) for the class, a colon appears followed by a list of base specifications. The base classes so
named must have been declared previously. The base specifications may contain an access specifier, which is
one of the keywords public , protected or private . These access specifiers appear before the base class name
and apply only to that base class. These specifiers control the derived class's permission to use to members of
the base class. See Member-Access Control for information on access to base class members. If the access
specifier is omitted, the access to that base is considered private . The base specifications may contain the
keyword virtual to indicate virtual inheritance. This keyword may appear before or after the access specifier, if
any. If virtual inheritance is used, the base class is referred to as a virtual base class.
Multiple base classes can be specified, separated by commas. If a single base class is specified, the inheritance
model is Single inheritance. If more than one base class is specified, the inheritance model is called Multiple
inheritance.
The following topics are included:
Single inheritance
Multiple base classes
Virtual functions
Explicit overrides
Abstract classes
Summary of scope rules
The __super and __interface keywords are documented in this section.
See also
C++ Language Reference
Virtual Functions
3/6/2021 • 4 minutes to read • Edit Online
A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a
derived class object using a pointer or a reference to the base class, you can call a virtual function for that object
and execute the derived class's version of the function.
Virtual functions ensure that the correct function is called for an object, regardless of the expression used to
make the function call.
Suppose a base class contains a function declared as virtual and a derived class defines the same function. The
function from the derived class is invoked for objects of the derived class, even if it is called using a pointer or
reference to the base class. The following example shows a base class that provides an implementation of the
PrintBalance function and two derived classes
// deriv_VirtualFunctions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Account {
public:
Account( double d ) { _balance = d; }
virtual ~Account() {}
virtual double GetBalance() { return _balance; }
virtual void PrintBalance() { cerr << "Error. Balance not available for base type." << endl; }
private:
double _balance;
};
int main() {
// Create objects of type CheckingAccount and SavingsAccount.
CheckingAccount checking( 100.00 );
SavingsAccount savings( 1000.00 );
In the preceding code, the calls to PrintBalance are identical, except for the object pAccount points to. Because
PrintBalance is virtual, the version of the function defined for each object is called. The PrintBalance function
in the derived classes CheckingAccount and SavingsAccount "override" the function in the base class Account .
If a class is declared that does not provide an overriding implementation of the PrintBalance function, the
default implementation from the base class Account is used.
Functions in derived classes override virtual functions in base classes only if their type is the same. A function in
a derived class cannot differ from a virtual function in a base class in its return type only; the argument list must
differ as well.
When calling a function using pointers or references, the following rules apply:
A call to a virtual function is resolved according to the underlying type of object for which it is called.
A call to a nonvirtual function is resolved according to the type of the pointer or reference.
The following example shows how virtual and nonvirtual functions behave when called through pointers:
// deriv_VirtualFunctions2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Base {
public:
virtual void NameOf(); // Virtual function.
void InvokingClass(); // Nonvirtual function.
};
void Base::InvokingClass() {
cout << "Invoked by Base\n";
}
void Derived::InvokingClass() {
cout << "Invoked by Derived\n";
}
int main() {
// Declare an object of type Derived.
Derived aDerived;
Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived
Note that regardless of whether the NameOf function is invoked through a pointer to Base or a pointer to
Derived , it calls the function for Derived . It calls the function for Derived because NameOf is a virtual function,
and both pBase and pDerived point to an object of type Derived .
Because virtual functions are called only for objects of class types, you cannot declare global or static functions
as virtual .
The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary;
overrides of virtual functions are always virtual.
Virtual functions in a base class must be defined unless they are declared using the pure-specifier. (For more
information about pure virtual functions, see Abstract Classes.)
The virtual function-call mechanism can be suppressed by explicitly qualifying the function name using the
scope-resolution operator ( :: ). Consider the earlier example involving the Account class. To call PrintBalance
in the base class, use code such as the following:
Both calls to PrintBalance in the preceding example suppress the virtual function-call mechanism.
Single Inheritance
3/6/2021 • 4 minutes to read • Edit Online
In "single inheritance," a common form of inheritance, classes have only one base class. Consider the
relationship illustrated in the following figure.
One other item of note in the figure: Book is both a derived class (from PrintedDocument ) and a base class (
PaperbackBook is derived from Book ). A skeletal declaration of such a class hierarchy is shown in the following
example:
// deriv_SingleInheritance.cpp
// compile with: /LD
class PrintedDocument {};
PrintedDocument is considered a "direct base" class to Book ; it is an "indirect base" class to PaperbackBook . The
difference is that a direct base class appears in the base list of a class declaration and an indirect base does not.
The base class from which each class is derived is declared before the declaration of the derived class. It is not
sufficient to provide a forward-referencing declaration for a base class; it must be a complete declaration.
In the preceding example, the access specifier public is used. The meaning of public, protected, and private
inheritance is described in Member-Access Control.
A class can serve as the base class for many specific classes, as illustrated in the following figure.
In inheritance, the derived class contains the members of the base class plus any new members you add. As a
result, a derived class can refer to members of the base class (unless those members are redefined in the
derived class). The scope-resolution operator ( :: ) can be used to refer to members of direct or indirect base
classes when those members have been redefined in the derived class. Consider this example:
// deriv_SingleInheritance2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;
class Document {
public:
char *Name; // Document name.
void PrintNameOf(); // Print name.
};
Note that the constructor for Book , ( Book::Book ), has access to the data member, Name . In a program, an object
of type Book can be created and used as follows:
...
As the preceding example demonstrates, class-member and inherited data and functions are used identically. If
the implementation for class Book calls for a reimplementation of the PrintNameOf function, the function that
belongs to the Document class can be called only by using the scope-resolution ( :: ) operator:
// deriv_SingleInheritance3.cpp
// compile with: /EHsc /LD
#include <iostream>
using namespace std;
class Document {
public:
char *Name; // Document name.
void PrintNameOf() {} // Print name.
};
void Book::PrintNameOf() {
cout << "Name of book: ";
Document::PrintNameOf();
}
Pointers and references to derived classes can be implicitly converted to pointers and references to their base
classes if there is an accessible, unambiguous base class. The following code demonstrates this concept using
pointers (the same principle applies to references):
// deriv_SingleInheritance4.cpp
// compile with: /W3
struct Document {
char *Name;
void PrintNameOf() {}
};
int main() {
Document * DocLib[10]; // Library of ten documents.
for (int i = 0 ; i < 5 ; i++)
DocLib[i] = new Document;
for (int i = 5 ; i < 10 ; i++)
DocLib[i] = new PaperbackBook;
}
In the preceding example, different types are created. However, because these types are all derived from the
Document class, there is an implicit conversion to Document * . As a result, DocLib is a "heterogeneous list" (a list
in which not all objects are of the same type) containing different kinds of objects.
Because the Document class has a PrintNameOf function, it can print the name of each book in the library,
although it may omit some of the information specific to the type of document (page count for Book , number
of bytes for HelpFile , and so on).
NOTE
Forcing the base class to implement a function such as PrintNameOf is often not the best design. Virtual Functions
offers other design alternatives.
Base Classes
3/6/2021 • 2 minutes to read • Edit Online
The inheritance process creates a new derived class that is made up of the members of the base class(es) plus
any new members added by the derived class. In a multiple-inheritance, it is possible to construct an inheritance
graph where the same base class is part of more than one of the derived classes. The following figure shows
such a graph.
A class can be derived from more than one base class. In a multiple-inheritance model (where classes are
derived from more than one base class), the base classes are specified using the base-list grammar element. For
example, the class declaration for CollectionOfBook , derived from Collection and Book , can be specified:
// deriv_MultipleBaseClasses.cpp
// compile with: /LD
class Collection {
};
class Book {};
class CollectionOfBook : public Book, public Collection {
// New members
};
The order in which base classes are specified is not significant except in certain cases where constructors and
destructors are invoked. In these cases, the order in which base classes are specified affects the following:
The order in which initialization by constructor takes place. If your code relies on the Book portion of
CollectionOfBook to be initialized before the Collection part, the order of specification is significant.
Initialization takes place in the order the classes are specified in the base-list.
The order in which destructors are invoked to clean up. Again, if a particular "part" of the class must be
present when the other part is being destroyed, the order is significant. Destructors are called in the
reverse order of the classes specified in the base-list.
NOTE
The order of specification of base classes can affect the memory layout of the class. Do not make any
programming decisions based on the order of base members in memory.
When specifying the base-list, you cannot specify the same class name more than once. However, it is possible
for a class to be an indirect base to a derived class more than once.
// deriv_VirtualBaseClasses.cpp
// compile with: /LD
class Queue {};
class CashierQueue : virtual public Queue {};
class LunchQueue : virtual public Queue {};
class LunchCashierQueue : public LunchQueue, public CashierQueue {};
The virtual keyword ensures that only one copy of the subobject Queue is included (see the following figure).
NOTE
Virtual inheritance provides significant size benefits when compared with nonvirtual inheritance. However, it can introduce
extra processing overhead.
If a derived class overrides a virtual function that it inherits from a virtual base class, and if a constructor or a
destructor for the derived base class calls that function using a pointer to the virtual base class, the compiler
may introduce additional hidden "vtordisp" fields into the classes with virtual bases. The /vd0 compiler option
suppresses the addition of the hidden vtordisp constructor/destructor displacement member. The /vd1
compiler option, the default, enables them where they are necessary. Turn off vtordisps only if you are sure that
all class constructors and destructors call virtual functions virtually.
The /vd compiler option affects an entire compilation module. Use the vtordisp pragma to suppress and then
reenable vtordisp fields on a class-by-class basis:
Name ambiguities
Multiple inheritance introduces the possibility for names to be inherited along more than one path. The class-
member names along these paths are not necessarily unique. These name conflicts are called "ambiguities."
Any expression that refers to a class member must make an unambiguous reference. The following example
shows how ambiguities develop:
// deriv_NameAmbiguities.cpp
// compile with: /LD
// Declare two base classes, A and B.
class A {
public:
unsigned a;
unsigned b();
};
class B {
public:
unsigned a(); // Note that class A also has a member "a"
int b(); // and a member "b".
char c;
};
Given the preceding class declarations, code such as the following is ambiguous because it is unclear whether
b refers to the b in A or in B :
C *pc = new C;
pc->b();
Consider the preceding example. Because the name a is a member of both class A and class B , the compiler
cannot discern which a designates the function to be called. Access to a member is ambiguous if it can refer to
more than one function, object, type, or enumerator.
The compiler detects ambiguities by performing tests in this order:
1. If access to the name is ambiguous (as just described), an error message is generated.
2. If overloaded functions are unambiguous, they are resolved.
3. If access to the name violates member-access permission, an error message is generated. (For more
information, see Member-Access Control.)
When an expression produces an ambiguity through inheritance, you can manually resolve it by qualifying the
name in question with its class name. To make the preceding example compile properly with no ambiguities, use
code such as:
C *pc = new C;
pc->B::a();
NOTE
When C is declared, it has the potential to cause errors when B is referenced in the scope of C . No error is issued,
however, until an unqualified reference to B is actually made in C 's scope.
Dominance
It is possible for more than one name (function, object, or enumerator) to be reached through an inheritance
graph. Such cases are considered ambiguous with nonvirtual base classes. They are also ambiguous with virtual
base classes, unless one of the names "dominates" the others.
A name dominates another name if it is defined in both classes and one class is derived from the other. The
dominant name is the name in the derived class; this name is used when an ambiguity would otherwise have
arisen, as shown in the following example:
// deriv_Dominance.cpp
// compile with: /LD
class A {
public:
int a;
};
Ambiguous conversions
Explicit and implicit conversions from pointers or references to class types can cause ambiguities. The next
figure, Ambiguous Conversion of Pointers to Base Classes, shows the following:
The declaration of an object of type D .
The effect of applying the address-of operator (& ) to that object. Note that the address-of operator
always supplies the base address of the object.
The effect of explicitly converting the pointer obtained using the address-of operator to the base-class
type A . Note that coercing the address of the object to type A* does not always provide the compiler
with enough information as to which subobject of type A to select; in this case, two subobjects exist.
See also
Inheritance
Explicit Overrides (C++)
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
If the same virtual function is declared in two or more interfaces and if a class is derived from these interfaces,
you can explicitly override each virtual function.
For information on explicit overrides in managed code using C++/CLI, see Explicit Overrides.
END Microsoft Specific
Example
The following code example illustrates how to use explicit overrides:
// deriv_ExplicitOverrides.cpp
// compile with: /GR
extern "C" int printf_s(const char *, ...);
__interface IMyInt1 {
void mf1();
void mf1(int);
void mf2();
void mf2(int);
};
__interface IMyInt2 {
void mf1();
void mf1(int);
void mf2();
void mf2(int);
};
void IMyInt1::mf1(int) {
printf_s("In CMyClass::IMyInt1::mf1(int)\n");
}
void IMyInt1::mf2();
void IMyInt1::mf2(int);
void IMyInt2::mf1() {
printf_s("In CMyClass::IMyInt2::mf1()\n");
}
void IMyInt2::mf1(int) {
printf_s("In CMyClass::IMyInt2::mf1(int)\n");
}
void IMyInt2::mf2();
void IMyInt2::mf2(int);
};
void CMyClass::IMyInt1::mf2() {
printf_s("In CMyClass::IMyInt1::mf2()\n");
printf_s("In CMyClass::IMyInt1::mf2()\n");
}
void CMyClass::IMyInt1::mf2(int) {
printf_s("In CMyClass::IMyInt1::mf2(int)\n");
}
void CMyClass::IMyInt2::mf2() {
printf_s("In CMyClass::IMyInt2::mf2()\n");
}
void CMyClass::IMyInt2::mf2(int) {
printf_s("In CMyClass::IMyInt2::mf2(int)\n");
}
int main() {
IMyInt1 *pIMyInt1 = new CMyClass();
IMyInt2 *pIMyInt2 = dynamic_cast<IMyInt2 *>(pIMyInt1);
pIMyInt1->mf1();
pIMyInt1->mf1(1);
pIMyInt1->mf2();
pIMyInt1->mf2(2);
pIMyInt2->mf1();
pIMyInt2->mf1(3);
pIMyInt2->mf2();
pIMyInt2->mf2(4);
In CMyClass::IMyInt1::mf1()
In CMyClass::IMyInt1::mf1(int)
In CMyClass::IMyInt1::mf2()
In CMyClass::IMyInt1::mf2(int)
In CMyClass::IMyInt2::mf1()
In CMyClass::IMyInt2::mf1(int)
In CMyClass::IMyInt2::mf2()
In CMyClass::IMyInt2::mf2(int)
See also
Inheritance
Abstract classes (C++)
4/9/2021 • 2 minutes to read • Edit Online
Abstract classes act as expressions of general concepts from which more specific classes can be derived. You
can't create an object of an abstract class type. However, you can use pointers and references to abstract class
types.
You create an abstract class by declaring at least one pure virtual member function. That's a virtual function
declared by using the pure specifier ( = 0 ) syntax. Classes derived from the abstract class must implement the
pure virtual function or they, too, are abstract classes.
Consider the example presented in Virtual functions. The intent of class Account is to provide general
functionality, but objects of type Account are too general to be useful. That means Account is a good candidate
for an abstract class:
// deriv_AbstractClasses.cpp
// compile with: /LD
class Account {
public:
Account( double d ); // Constructor.
virtual double GetBalance(); // Obtain balance.
virtual void PrintBalance() = 0; // Pure virtual function.
private:
double _balance;
};
The only difference between this declaration and the previous one is that PrintBalance is declared with the pure
specifier ( = 0 ).
int main()
{
derived aDerived; // destructor called when it goes out of scope
}
The example shows how a Microsoft compiler extension lets you add an inline definition to pure virtual ~base()
. You can also define it outside the class by using base::~base() {} .
When the object aDerived goes out of scope, the destructor for class derived is called. The compiler generates
code to implicitly call the destructor for class base after the derived destructor. The empty implementation for
the pure virtual function ~base ensures that at least some implementation exists for the function. Without it, the
linker generates an unresolved external symbol error for the implicit call.
NOTE
In the preceding example, the pure virtual function base::~base is called implicitly from derived::~derived . It's also
possible to call pure virtual functions explicitly by using a fully qualified member-function name. Such functions must have
an implementation, or the call results in an error at link time.
See also
Inheritance
Summary of Scope Rules
3/6/2021 • 2 minutes to read • Edit Online
The use of a name must be unambiguous within its scope (up to the point where overloading is determined). If
the name denotes a function, the function must be unambiguous with respect to number and type of
parameters. If the name remains unambiguous, member-access rules are applied.
Constructor initializers
Constructor initializers are evaluated in the scope of the outermost block of the constructor for which they are
specified. Therefore, they can use the constructor's parameter names.
Global names
A name of an object, function, or enumerator is global if it is introduced outside any function or class or prefixed
by the global unary scope operator ( :: ), and if it is not used in conjunction with any of these binary operators:
Scope-resolution ( :: )
Member-selection for objects and references (.)
Member-selection for pointers (-> )
Qualified names
Names used with the binary scope-resolution operator ( :: ) are called "qualified names." The name specified
after the binary scope-resolution operator must be a member of the class specified on the left of the operator or
a member of its base class(es).
Names specified after the member-selection operator (. or -> ) must be members of the class type of the object
specified on the left of the operator or members of its base class(es). Names specified on the right of the
member-selection operator (-> ) can also be objects of another class type, provided that the left-hand side of ->
is a class object and that the class defines an overloaded member-selection operator (-> ) that evaluates to a
pointer to some other class type. (This provision is discussed in more detail in Class Member Access.)
The compiler searches for names in the following order, stopping when the name is found:
1. Current block scope if name is used inside a function; otherwise, global scope.
2. Outward through each enclosing block scope, including the outermost function scope (which includes
function parameters).
3. If the name is used inside a member function, the class's scope is searched for the name.
4. The class's base classes are searched for the name.
5. The enclosing nested class scope (if any) and its bases are searched. The search continues until the
outermost enclosing class scope is searched.
6. Global scope is searched.
However, you can make modifications to this search order as follows:
1. Names preceded by :: force the search to begin at global scope.
2. Names preceded by the class , struct , and union keywords force the compiler to search only for
class , struct , or union names.
3. Names on the left side of the scope-resolution operator ( :: ) can be only class , struct , namespace , or
union names.
If the name refers to a nonstatic member but is used in a static member function, an error message is generated.
Similarly, if the name refers to any nonstatic member in an enclosing class, an error message is generated
because enclosed classes do not have enclosing-class this pointers.
See also
Inheritance
Inheritance keywords
4/18/2021 • 2 minutes to read • Edit Online
Microsoft Specific
class class-name
class __single_inheritance class-name
class __multiple_inheritance class-name
class __virtual_inheritance class-name
where:
class-name
The name of the class being declared.
C++ allows you to declare a pointer to a class member before the definition of the class. For example:
class S;
int S::*p;
In the code above, p is declared to be a pointer to integer member of class S. However, class S hasn't been
defined yet in this code; it's only been declared. When the compiler encounters such a pointer, it must make a
generalized representation of the pointer. The size of the representation is dependent on the inheritance model
specified. There are three ways to specify an inheritance model to the compiler:
At the command line using the /vmg switch
Using the pointers_to_members pragma
Using the inheritance keywords __single_inheritance , __multiple_inheritance , and
__virtual_inheritance . This technique controls the inheritance model on a per-class basis.
NOTE
If you always declare a pointer to a member of a class after defining the class, you don't need to use any of these
options.
If you declare a pointer to a class member before the class is defined, it can negatively affect the size and speed
of the resulting executable file. The more complex the inheritance used by a class, the greater the number of
bytes required to represent a pointer to a member of the class. And, the larger the code required to interpret the
pointer. Single (or no) inheritance is least complex, and virtual inheritance is most complex. Pointers to members
you declare before the class is defined always use the largest, most complex representation.
If the example above is changed to:
class __single_inheritance S;
int S::*p;
then no matter the command-line options or pragmas you specify, pointers to members of class S will use the
smallest possible representation.
NOTE
The same forward declaration of a class pointer-to-member representation should occur in every translation unit that
declares pointers to members of that class, and the declaration should occur before the pointers to members are declared.
See also
Keywords
virtual (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
virtual [type-specifiers] member-function-declarator
virtual [access-specifier] base-class-name
Parameters
type-specifiers
Specifies the return type of the virtual member function.
member-function-declarator
Declares a member function.
access-specifier
Defines the level of access to the base class, public , protected or private . Can appear before or after the
virtual keyword.
base-class-name
Identifies a previously declared class type.
Remarks
See Virtual Functions for more information.
Also see the following keywords: class, private, public, and protected.
See also
Keywords
__super
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Allows you to explicitly state that you are calling a base-class implementation for a function that you are
overriding.
Syntax
__super::member_function();
Remarks
All accessible base-class methods are considered during the overload resolution phase, and the function that
provides the best match is the one that is called.
__super can only appear within the body of a member function.
__super cannot be used with a using declaration. See using Declaration for more information.
With the introduction of attributes that inject code, your code might contain one or more base classes whose
names you may not know but that contain methods that you wish to call.
Example
// deriv_super.cpp
// compile with: /c
struct B1 {
void mf(int) {}
};
struct B2 {
void mf(short) {}
void mf(char) {}
};
struct D : B1, B2 {
void mf(short) {
__super::mf(1); // Calls B1::mf(int)
__super::mf('s'); // Calls B2::mf(char)
}
};
See also
Keywords
__interface
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
A Microsoft C++ interface can be defined as follows:
Can inherit from zero or more base interfaces.
Cannot inherit from a base class.
Can only contain public, pure virtual methods.
Cannot contain constructors, destructors, or operators.
Cannot contain static methods.
Cannot contain data members; properties are allowed.
Syntax
modifier __interface interface-name {interface-definition};
Remarks
A C++ class or struct could be implemented with these rules, but __interface enforces them.
For example, the following is a sample interface definition:
__interface IMyInterface {
HRESULT CommitX();
HRESULT get_X(BSTR* pbstrName);
};
Example
The following sample shows how to use properties declared in an interface.
// deriv_interface.cpp
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>
#include <string.h>
#include <comdef.h>
#include <comdef.h>
#include <stdio.h>
[module(name="test")];
[ coclass, uuid("00000000-0000-0000-0000-000000000002") ]
class MyClass : public IFace {
private:
int m_i;
BSTR m_bstr;
public:
MyClass()
{
m_i = 0;
m_bstr = 0;
}
~MyClass()
{
if (m_bstr)
::SysFreeString(m_bstr);
}
int get_int_data()
{
return m_i;
}
BSTR get_bstr_data()
{
BSTR bstr = ::SysAllocString(m_bstr);
return bstr;
}
int main()
{
_bstr_t bstr("Testing");
CoInitialize(NULL);
CComObject<MyClass>* p;
CComObject<MyClass>::CreateInstance(&p);
p->int_data = 100;
printf_s("p->int_data = %d\n", p->int_data);
p->bstr_data = bstr;
printf_s("bstr_data = %S\n", p->bstr_data);
}
p->int_data = 100
bstr_data = Testing
See also
Keywords
Interface Attributes
Special member functions
3/6/2021 • 2 minutes to read • Edit Online
The special member functions are class (or struct) member functions that, in certain cases, the compiler
automatically generates for you. These functions are the default constructor, the destructor, the copy constructor
and copy assignment operator, and the move constructor and move assignment operator. If your class does not
define one or more of the special member functions, then the compiler may implicitly declare and define the
functions that are used. The compiler-generated implementations are called the default special member
functions. The compiler does not generate functions if they are not needed.
You can explicitly declare a default special member function by using the = default keyword. This causes the
compiler to define the function only if needed, in the same way as if the function was not declared at all.
In some cases, the compiler may generate deleted special member functions, which are not defined and
therefore not callable. This can happen in cases where a call to a particular special member function on a class
doesn't make sense, given other properties of the class. To explicitly prevent automatic generation of a special
member function, you can declare it as deleted by using the = delete keyword.
The compiler generates a default constructor, a constructor that takes no arguments, only when you have not
declared any other constructor. If you have declared only a constructor that takes parameters, code that attempts
to call a default constructor causes the compiler to produce an error message. The compiler-generated default
constructor performs simple member-wise default initialization of the object. Default initialization leaves all
member variables in an indeterminate state.
The default destructor performs member-wise destruction of the object. It is virtual only if a base class
destructor is virtual.
The default copy and move construction and assignment operations perform member-wise bit-pattern copies or
moves of non-static data members. Move operations are only generated when no destructor or move or copy
operations are declared. A default copy constructor is only generated when no copy constructor is declared. It is
implicitly deleted if a move operation is declared. A default copy assignment operator is generated only when
no copy assignment operator is explicitly declared. It is implicitly deleted if a move operation is declared.
See also
C++ Language Reference
Static Members (C++)
3/6/2021 • 2 minutes to read • Edit Online
Classes can contain static member data and member functions. When a data member is declared as static ,
only one copy of the data is maintained for all objects of the class.
Static data members are not part of objects of a given class type. As a result, the declaration of a static data
member is not considered a definition. The data member is declared in class scope, but definition is performed
at file scope. These static members have external linkage. The following example illustrates this:
// static_data_members.cpp
class BufferedOutput
{
public:
// Return number of bytes written by any object of this class.
short BytesWritten()
{
return bytecount;
}
int main()
{
}
In the preceding code, the member bytecount is declared in class BufferedOutput , but it must be defined
outside the class declaration.
Static data members can be referred to without referring to an object of class type. The number of bytes written
using BufferedOutput objects can be obtained as follows:
For the static member to exist, it is not necessary that any objects of the class type exist. Static members can also
be accessed using the member-selection (. and -> ) operators. For example:
BufferedOutput Console;
In the preceding case, the reference to the object ( Console ) is not evaluated; the value returned is that of the
static object bytecount .
Static data members are subject to class-member access rules, so private access to static data members is
allowed only for class-member functions and friends. These rules are described in Member-Access Control. The
exception is that static data members must be defined in file scope regardless of their access restrictions. If the
data member is to be explicitly initialized, an initializer must be provided with the definition.
The type of a static member is not qualified by its class name. Therefore, the type of BufferedOutput::bytecount
is long .
See also
Classes and Structs
C++ classes as value types
3/6/2021 • 3 minutes to read • Edit Online
C++ classes are by default value types. They can be specified as reference types, which enable polymorphic
behavior to support object-oriented programming. Value types are sometimes viewed from the perspective of
memory and layout control, whereas reference types are about base classes and virtual functions for
polymorphic purposes. By default, value types are copyable, which means there is always a copy constructor and
a copy assignment operator. For reference types, you make the class non-copyable (disable the copy constructor
and copy assignment operator) and use a virtual destructor, which supports their intended polymorphism. Value
types are also about the contents, which, when they are copied, always give you two independent values that
can be modified separately. Reference types are about identity - what kind of object is it? For this reason,
"reference types" are also referred to as "polymorphic types".
If you really want a reference-like type (base class, virtual functions), you need to explicitly disable copying, as
shown in the MyRefType class in the following code.
class MyRefType {
private:
MyRefType & operator=(const MyRefType &);
MyRefType(const MyRefType &);
public:
MyRefType () {}
};
int main()
{
MyRefType Data1, Data2;
// ...
Data1 = Data2;
}
test.cpp(15) : error C2248: 'MyRefType::operator =' : cannot access private member declared in class
'MyRefType'
meow.cpp(5) : see declaration of 'MyRefType::operator ='
meow.cpp(3) : see declaration of 'MyRefType'
#include <set>
#include <vector>
#include <string>
using namespace std;
//...
set<widget> LoadHugeData() {
set<widget> ret;
// ... load data from disk and populate ret
return ret;
}
//...
widgets = LoadHugeData(); // efficient, no deep copy
vector<string> v = IfIHadAMillionStrings();
v.insert( begin(v)+v.size()/2, "scott" ); // efficient, no deep copy-shuffle
v.insert( begin(v)+v.size()/2, "Andrei" ); // (just 1M ptr/len assignments)
//...
HugeMatrix operator+(const HugeMatrix& , const HugeMatrix& );
HugeMatrix operator+(const HugeMatrix& , HugeMatrix&&);
HugeMatrix operator+( HugeMatrix&&, const HugeMatrix& );
HugeMatrix operator+( HugeMatrix&&, HugeMatrix&&);
//...
hm5 = hm1+hm2+hm3+hm4+hm5; // efficient, no extra copies
#include <memory>
#include <stdexcept>
using namespace std;
// ...
class my_class {
unique_ptr<BigHugeData> data;
public:
my_class( my_class&& other ) // move construction
: data( move( other.data ) ) { }
my_class& operator=( my_class&& other ) // move assignment
{ data = move( other.data ); return *this; }
// ...
void method() { // check (if appropriate)
if( !data )
throw std::runtime_error("RUNTIME ERROR: Insufficient resources!");
}
};
If you enable copy construction/assignment, also enable move construction/assignment if it can be cheaper than
a deep copy.
Some non-value types are move-only, such as when you can’t clone a resource, only transfer ownership.
Example: unique_ptr .
See also
C++ type system
Welcome back to C++
C++ Language Reference
C++ Standard Library
User-Defined Type Conversions (C++)
3/6/2021 • 10 minutes to read • Edit Online
A conversion produces a new value of some type from a value of a different type. Standard conversions are built
into the C++ language and support its built-in types, and you can create user-defined conversions to perform
conversions to, from, or between user-defined types.
The standard conversions perform conversions between built-in types, between pointers or references to types
related by inheritance, to and from void pointers, and to the null pointer. For more information, see Standard
Conversions. User-defined conversions perform conversions between user-defined types, or between user-
defined types and built-in types. You can implement them as Conversion constructors or as Conversion
functions.
Conversions can either be explicit—when the programmer calls for one type to be converted to another, as in a
cast or direct initialization—or implicit—when the language or program calls for a different type than the one
given by the programmer.
Implicit conversions are attempted when:
An argument supplied to a function does not have the same type as the matching parameter.
The value returned from a function does not have the same type as the function return type.
An initializer expression does not have the same type as the object it is initializing.
An expression that controls a conditional statement, looping construct, or switch does not have the result
type that's required to control it.
An operand supplied to an operator does not have the same type as the matching operand-parameter.
For built-in operators, both operands must have the same type, and are converted to a common type that
can represent both. For more information, see Standard Conversions. For user-defined operators, each
operand must have the same type as the matching operand-parameter.
When one standard conversion can't complete an implicit conversion, the compiler can use a user-defined
conversion, followed optionally by an additional standard conversion, to complete it.
When two or more user-defined conversions that perform the same conversion are available at a conversion
site, the conversion is said to be ambiguous. Such ambiguities are an error because the compiler can't determine
which one of the available conversions it should choose. However, it's not an error just to define multiple ways
of performing the same conversion because the set of available conversions can be different at different
locations in the source code—for example, depending on which header files are included in a source file. As long
as only one conversion is available at the conversion site, there is no ambiguity. There are several ways that
ambiguous conversions can arise, but the most common ones are:
Multiple inheritance. The conversion is defined in more than one base class.
Ambiguous function call. The conversion is defined as a conversion constructor of the target type and as
a conversion function of the source type. For more information, see Conversion functions.
You can usually resolve an ambiguity just by qualifying the name of the involved type more fully or by
performing an explicit cast to clarify your intent.
Both conversion constructors and conversion functions obey member-access control rules, but the accessibility
of the conversions is only considered if and when an unambiguous conversion can be determined. This means
that a conversion can be ambiguous even if the access level of a competing conversion would prevent it from
being used. For more information about member accessibility, see Member Access Control.
Conversion constructors
Conversion constructors define conversions from user-defined or built-in types to a user-defined type. The
following example demonstrates a conversion constructor that converts from the built-in type double to a user-
defined type Money .
#include <iostream>
class Money
{
public:
Money() : amount{ 0.0 } {};
Money(double _amount) : amount{ _amount } {};
double amount;
};
display_balance(payable);
display_balance(49.95);
display_balance(9.99f);
return 0;
}
Notice that the first call to the function display_balance , which takes an argument of type Money , doesn't
require a conversion because its argument is the correct type. However, on the second call to display_balance , a
conversion is needed because the type of the argument, a double with a value of 49.95 , is not what the
function expects. The function can't use this value directly, but because there's a conversion from the type of the
argument— double —to the type of the matching parameter— Money —a temporary value of type Money is
constructed from the argument and used to complete the function call. In the third call to display_balance ,
notice that the argument is not a double , but is instead a float with a value of 9.99 —and yet the function call
can still be completed because the compiler can perform a standard conversion—in this case, from float to
double —and then perform the user-defined conversion from double to Money to complete the necessary
conversion.
Declaring conversion constructors
The following rules apply to declaring a conversion constructor:
The target type of the conversion is the user-defined type that's being constructed.
Conversion constructors typically take exactly one argument, which is of the source type. However, a
conversion constructor can specify additional parameters if each additional parameter has a default
value. The source type remains the type of the first parameter.
Conversion constructors, like all constructors, do not specify a return type. Specifying a return type in the
declaration is an error.
Conversion constructors can be explicit.
Explicit conversion constructors
By declaring a conversion constructor to be explicit , it can only be used to perform direct initialization of an
object or to perform an explicit cast. This prevents functions that accept an argument of the class type from also
implicitly accepting arguments of the conversion constructor's source type, and prevents the class type from
being copy-initialized from a value of the source type. The following example demonstrates how to define an
explicit conversion constructor, and the effect it has on what code is well-formed.
#include <iostream>
class Money
{
public:
Money() : amount{ 0.0 } {};
explicit Money(double _amount) : amount{ _amount } {};
double amount;
};
return 0;
}
In this example, notice that you can still use the explicit conversion constructor to perform direct initialization of
payable . If instead you were to copy-initialize Money payable = 79.99; , it would be an error. The first call to
display_balance is unaffected because the argument is the correct type. The second call to display_balance is
an error, because the conversion constructor can't be used to perform implicit conversions. The third call to
display_balance is legal because of the explicit cast to Money , but notice that the compiler still helped complete
the cast by inserting an implicit cast from float to double .
Although the convenience of allowing implicit conversions can be tempting, doing so can introduce hard-to-find
bugs. The rule of thumb is to make all conversion constructors explicit except when you're sure that you want a
specific conversion to occur implicitly.
Conversion functions
Conversion functions define conversions from a user-defined type to other types. These functions are
sometimes referred to as "cast operators" because they, along with conversion constructors, are called when a
value is cast to a different type. The following example demonstrates a conversion function that converts from
the user-defined type, Money , to a built-in type, double :
#include <iostream>
class Money
{
public:
Money() : amount{ 0.0 } {};
Money(double _amount) : amount{ _amount } {};
Notice that the member variable amount is made private and that a public conversion function to type double
is introduced just to return the value of amount . In the function display_balance , an implicit conversion occurs
when the value of balance is streamed to standard output by using the stream insertion operator << . Because
no stream-insertion operator is defined for the user-defined type Money , but there is one for built-in type
double , the compiler can use the conversion function from Money to double to satisfy the stream-insertion
operator.
Conversion functions are inherited by derived classes. Conversion functions in a derived class only override an
inherited conversion function when they convert to exactly the same type. For example, a user-defined
conversion function of the derived class operator int does not override—or even influence—a user-defined
conversion function of the base class operator shor t , even though the standard conversions define a
conversion relationship between int and short .
Declaring conversion functions
The following rules apply to declaring a conversion function:
The target type of the conversion must be declared prior to the declaration of the conversion function.
Classes, structures, enumerations, and typedefs cannot be declared within the declaration of the
conversion function.
Conversion functions take no arguments. Specifying any parameters in the declaration is an error.
Conversion functions have a return type that is specified by the name of the conversion function, which is
also the name of the conversion's target type. Specifying a return type in the declaration is an error.
Conversion functions can be virtual.
Conversion functions can be explicit.
Explicit conversion functions
When a conversion function is declared to be explicit, it can only be used to perform an explicit cast. This
prevents functions that accept an argument of the conversion function's target type from also implicitly
accepting arguments of the class type, and prevents instances of the target type from being copy-initialized
from a value of the class type. The following example demonstrates how to define an explicit conversion
function and the effect it has on what code is well-formed.
#include <iostream>
class Money
{
public:
Money() : amount{ 0.0 } {};
Money(double _amount) : amount{ _amount } {};
Here the conversion function operator double has been made explicit, and an explicit cast to type double has
been introduced in the function display_balance to perform the conversion. If this cast were omitted, the
compiler would be unable to locate a suitable stream-insertion operator << for type Money and an error would
occur.
Mutable Data Members (C++)
3/6/2021 • 2 minutes to read • Edit Online
This keyword can only be applied to non-static and non-const data members of a class. If a data member is
declared mutable , then it is legal to assign a value to this data member from a const member function.
Syntax
mutable member-variable-declaration;
Remarks
For example, the following code will compile without error because m_accessCount has been declared to be
mutable , and therefore can be modified by GetFlag even though GetFlag is a const member function.
// mutable.cpp
class X
{
public:
bool GetFlag() const
{
m_accessCount++;
return m_flag;
}
private:
bool m_flag;
mutable int m_accessCount;
};
int main()
{
}
See also
Keywords
Nested Class Declarations
3/6/2021 • 4 minutes to read • Edit Online
A class can be declared within the scope of another class. Such a class is called a "nested class." Nested classes
are considered to be within the scope of the enclosing class and are available for use within that scope. To refer
to a nested class from a scope other than its immediate enclosing scope, you must use a fully qualified name.
The following example shows how to declare nested classes:
// nested_class_declarations.cpp
class BufferedIO
{
public:
enum IOError { None, Access, General };
int main()
{
}
BufferedIO::BufferedInput and BufferedIO::BufferedOutput are declared within BufferedIO . These class names
are not visible outside the scope of class BufferedIO . However, an object of type BufferedIO does not contain
any objects of types BufferedInput or BufferedOutput .
Nested classes can directly use names, type names, names of static members, and enumerators only from the
enclosing class. To use names of other class members, you must use pointers, references, or object names.
In the preceding BufferedIO example, the enumeration IOError can be accessed directly by member functions
in the nested classes, BufferedIO::BufferedInput or BufferedIO::BufferedOutput , as shown in function good .
NOTE
Nested classes declare only types within class scope. They do not cause contained objects of the nested class to be
created. The preceding example declares two nested classes but does not declare any objects of these class types.
An exception to the scope visibility of a nested class declaration is when a type name is declared together with a
forward declaration. In this case, the class name declared by the forward declaration is visible outside the
enclosing class, with its scope defined to be the smallest enclosing non-class scope. For example:
// nested_class_declarations_2.cpp
class C
{
public:
typedef class U u_t; // class U visible outside class C scope
typedef class V {} v_t; // class V not visible outside class C
};
int main()
{
// okay, forward declaration used above so file scope is used
U* pu;
class BufferedOutput
{
// Member list.
};
};
// Define member functions read and good in
// file scope.
int BufferedIO::BufferedInput::read()
{
return(1);
}
int BufferedIO::BufferedInput::good()
{
return _inputerror == None;
}
int main()
{
}
In the preceding example, the qualified-type-name syntax is used to declare the function name. The declaration:
BufferedIO::BufferedInput::read()
means "the read function that is a member of the BufferedInput class that is in the scope of the BufferedIO
class." Because this declaration uses the qualified-type-name syntax, constructs of the following form are
possible:
int BIO_INPUT::read()
The preceding declaration is equivalent to the previous one, but it uses a typedef name in place of the class
names.
#include <string.h>
enum
{
sizeOfMessage = 255
};
char *rgszMessage[sizeOfMessage];
class BufferedIO
{
public:
class BufferedInput
{
public:
friend int GetExtendedErrorStatus();
static char *message;
static int messageSize;
int iMsgNo;
};
};
char *BufferedIO::BufferedInput::message;
int BufferedIO::BufferedInput::messageSize;
int GetExtendedErrorStatus()
{
int iMsgNo = 1; // assign arbitrary value as message number
strcpy_s( BufferedIO::BufferedInput::message,
BufferedIO::BufferedInput::messageSize,
rgszMessage[iMsgNo] );
return iMsgNo;
}
int main()
{
}
The following code shows the function GetExtendedErrorStatus declared as a friend function. In the function,
which is defined in file scope, a message is copied from a static array into a class member. Note that a better
implementation of GetExtendedErrorStatus is to declare it as:
With the preceding interface, several classes can use the services of this function by passing a memory location
where they want the error message copied.
See also
Classes and Structs
Anonymous Class Types
3/6/2021 • 2 minutes to read • Edit Online
Classes can be anonymous — that is, they can be declared without an identifier. This is useful when you replace
a class name with a typedef name, as in the following:
typedef struct
{
unsigned x;
unsigned y;
} POINT;
NOTE
The use of anonymous classes shown in the previous example is useful for preserving compatibility with existing C code.
In some C code, the use of typedef in conjunction with anonymous structures is prevalent.
Anonymous classes are also useful when you want a reference to a class member to appear as though it were
not contained in a separate class, as in the following:
struct PTValue
{
POINT ptLoc;
union
{
int iValue;
long lValue;
};
};
PTValue ptv;
In the preceding code, iValue can be accessed using the object member-selection operator (.) as follows:
int i = ptv.iValue;
Anonymous classes are subject to certain restrictions. (For more information about anonymous unions, see
Unions.) Anonymous classes:
Cannot have a constructor or destructor.
Cannot be passed as arguments to functions (unless type checking is defeated using ellipsis).
Cannot be returned as return values from functions.
Anonymous structs
Microsoft Specific
A Microsoft C extension allows you to declare a structure variable within another structure without giving it a
name. These nested structures are called anonymous structures. C++ does not allow anonymous structures.
You can access the members of an anonymous structure as if they were members in the containing structure.
// anonymous_structures.c
#include <stdio.h>
struct phone
{
int areacode;
long number;
};
struct person
{
char name[30];
char gender;
int age;
int weight;
struct phone; // Anonymous structure; no name needed
} Jim;
int main()
{
Jim.number = 1234567;
printf_s("%d\n", Jim.number);
}
//Output: 1234567
Declarations of pointers to members are special cases of pointer declarations. They're declared using the
following sequence:
In the preceding example, pwCaption is a pointer to any member of class Window that's of type char* . The type
of pwCaption is char * Window::* . The next code fragment declares pointers to the SetCaption and GetCaption
member functions.
The pointers pfnwGC and pfnwSC point to GetCaption and SetCaption of the Window class, respectively. The
code copies information to the window caption directly using the pointer to member pwCaption :
Window wMainWindow;
Window *pwChildWindow = new Window;
char *szUntitled = "Untitled - ";
int cUntitledLen = strlen( szUntitled );
The difference between the .* and ->* operators (the pointer-to-member operators) is that the .* operator
selects members given an object or object reference, while the ->* operator selects members through a
pointer. For more information about these operators, see Expressions with Pointer-to-Member Operators.
The result of the pointer-to-member operators is the type of the member. In this case, it's char * .
The following code fragment invokes the member functions GetCaption and SetCaption using pointers to
members:
// Allocate a buffer.
enum {
sizeOfBuffer = 100
};
char szCaptionBase[sizeOfBuffer];
class Base
{
public:
virtual void Print();
};
void (Base::* bfnPrint)() = &Base::Print;
void Base::Print()
{
cout << "Print function for class Base" << endl;
}
void Derived::Print()
{
cout << "Print function for class Derived" << endl;
}
int main()
{
Base *bPtr;
Base bObject;
Derived dObject;
bPtr = &bObject; // Set pointer to address of bObject.
(bPtr->*bfnPrint)();
bPtr = &dObject; // Set pointer to address of dObject.
(bPtr->*bfnPrint)();
}
// Output:
// Print function for class Base
// Print function for class Derived
this pointer
11/2/2020 • 3 minutes to read • Edit Online
The pointer is a pointer accessible only within the nonstatic member functions of a class , struct , or
this
union type. It points to the object for which the member function is called. Static member functions don't have a
this pointer.
Syntax
this
this->member-identifier
Remarks
An object's this pointer isn't part of the object itself. It's not reflected in the result of a sizeof statement on
the object. When a nonstatic member function is called for an object, the compiler passes the object's address to
the function as a hidden argument. For example, the following function call:
myDate.setMonth( 3 );
setMonth( &myDate, 3 );
The object's address is available from within the member function as the this pointer. Most this pointer uses
are implicit. It's legal, though unnecessary, to use an explicit this when referring to members of the class. For
example:
The expression *this is commonly used to return the current object from a member function:
return *this;
if (&Object != this) {
// do not execute in cases of self-reference
NOTE
Because the this pointer is nonmodifiable, assignments to the this pointer are not allowed. Earlier implementations
of C++ allowed assignment to this .
Occasionally, the this pointer is used directly — for example, to manipulate self-referential data structures,
where the address of the current object is required.
Example
// this_pointer.cpp
// compile with: /EHsc
#include <iostream>
#include <string.h>
class Buf
{
public:
Buf( char* szBuffer, size_t sizeOfBuffer );
Buf& operator=( const Buf & );
void Display() { cout << buffer << endl; }
private:
char* buffer;
size_t sizeOfBuffer;
};
int main()
{
Buf myBuf( "my buffer", 10 );
Buf yourBuf( "your buffer", 12 );
// assignment operator
myBuf = yourBuf;
my buffer
your buffer
Type of the this pointer
The this pointer's type can be modified in the function declaration by the const and volatile keywords. To
declare a function that has either of these attributes, add the keyword(s) after the function argument list.
Consider an example:
// type_of_this_pointer1.cpp
class Point
{
unsigned X() const;
};
int main()
{
}
The preceding code declares a member function, X , in which the this pointer is treated as a const pointer to
a const object. Combinations of cv-mod-list options can be used, but they always modify the object pointed to
by the this pointer, not the pointer itself. The following declaration declares function X , where the this
pointer is a const pointer to a const object:
// type_of_this_pointer2.cpp
class Point
{
unsigned X() const;
};
int main()
{
}
The type of this in a member function is described by the following syntax. The cv-qualifier-list is determined
from the member function's declarator. It can be const or volatile (or both). class-type is the name of the
class:
[cv-qualifier-list] class-type * const this
In other words, the this pointer is always a const pointer. It can't be reassigned. The const or volatile
qualifiers used in the member function declaration apply to the class instance the this pointer points at, in the
scope of that function.
The following table explains more about how these modifiers work.
Semantics of this modifiers
M O DIF IER M EA N IN G
It's an error to pass a const object to a member function that isn't const .
Similarly, it's also an error to pass a volatile object to a member function that isn't volatile .
Member functions declared as const can't change member data — in such functions, the this pointer is a
pointer to a const object.
NOTE
Constructors and destructors can't be declared as const or volatile . They can, however, be invoked on const or
volatile objects.
See also
Keywords
C++ Bit Fields
3/6/2021 • 2 minutes to read • Edit Online
Classes and structures can contain members that occupy less storage than an integral type. These members are
specified as bit fields. The syntax for bit-field member-declarator specification follows:
Syntax
declarator : constant-expression
Remarks
The (optional) declarator is the name by which the member is accessed in the program. It must be an integral
type (including enumerated types). The constant-expression specifies the number of bits the member occupies
in the structure. Anonymous bit fields — that is, bit-field members with no identifier — can be used for padding.
NOTE
An unnamed bit field of width 0 forces alignment of the next bit field to the next type boundary, where type is the type
of the member.
// bit_fields1.cpp
// compile with: /LD
struct Date {
unsigned short nWeekDay : 3; // 0..7 (3 bits)
unsigned short nMonthDay : 6; // 0..31 (6 bits)
unsigned short nMonth : 5; // 0..12 (5 bits)
unsigned short nYear : 8; // 0..100 (8 bits)
};
The conceptual memory layout of an object of type Date is shown in the following figure.
See also
Classes and Structs
Lambda Expressions in C++
3/6/2021 • 12 minutes to read • Edit Online
In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an
anonymous function object (a closure) right at the location where it is invoked or passed as an argument to a
function. Typically lambdas are used to encapsulate a few lines of code that are passed to algorithms or
asynchronous methods. This article defines what lambdas are, compares them to other programming
techniques, describes their advantages, and provides a basic example.
Related Topics
Lambda expressions vs. function objects
Working with lambda expressions
constexpr lambda expressions
#include <algorithm>
#include <cmath>
[&total, factor]
[factor, &total]
[&, factor]
[factor, &]
[=, &total]
[&total, =]
Only variables that are mentioned in the lambda are captured when a capture-default is used.
If a capture clause includes a capture-default & , then no identifier in a capture of that capture clause can
have the form & identifier . Likewise, if the capture clause includes a capture-default = , then no capture of
that capture clause can have the form = identifier . An identifier or this cannot appear more than once in a
capture clause. The following code snippet illustrates some examples.
void S::f(int i) {
[&, i]{}; // OK
[&, &i]{}; // ERROR: i preceded by & when & is the default
[=, this]{}; // ERROR: this when = is the default
[=, *this]{ }; // OK: captures this by value. See below.
[i, i]{}; // ERROR: i repeated
}
A capture followed by an ellipsis is a pack expansion, as shown in this variadic template example:
template<class... Args>
void f(Args... args) {
auto x = [args...] { return g(args...); };
x();
}
To use lambda expressions in the body of a class method, pass the this pointer to the capture clause to provide
access to the methods and data members of the enclosing class.
Visual Studio 2017 version 15.3 and later (available with /std:c++17): The this pointer may be captured
by value by specifying *this in the capture clause. Capture by value means that the entire closure, which is the
anonymous function object that encapulates the lambda expression, is copied to every call site where the
lambda is invoked. Capture by value is useful when the lambda will execute in parallel or asynchronous
operations, especially on certain hardware architectures such as NUMA.
For an example that shows how to use lambda expressions with class methods, see "Example: Using a Lambda
Expression in a Method" in Examples of Lambda Expressions.
When you use the capture clause, we recommend that you keep these points in mind, particularly when you use
lambdas with multithreading:
Reference captures can be used to modify variables outside, but value captures cannot. ( mutable allows
copies to be modified, but not originals.)
Reference captures reflect updates to variables outside, but value captures do not.
Reference captures introduce a lifetime dependency, but value captures have no lifetime dependencies.
This is especially important when the lambda runs asynchronously. If you capture a local by reference in
an async lambda, that local will very possibly be gone by the time the lambda runs, resulting in an access
violation at run time.
Generalized capture (C++ 14)
In C++14, you can introduce and initialize new variables in the capture clause, without the need to have those
variables exist in the lambda function’s enclosing scope. The initialization can be expressed as any arbitrary
expression; the type of the new variable is deduced from the type produced by the expression. One benefit of
this feature is that in C++14 you can capture move-only variables (such as std::unique_ptr) from the
surrounding scope and use them in a lambda.
pNums = make_unique<vector<int>>(nums);
//...
auto a = [ptr = move(pNums)]()
{
// use ptr
};
Parameter List
In addition to capturing variables, a lambda can accept input parameters. A parameter list (lambda declarator in
the Standard syntax) is optional and in most aspects resembles the parameter list for a function.
In C++14 , if the parameter type is generic, you can use the auto keyword as the type specifier. This tells the
compiler to create the function call operator as a template. Each instance of auto in a parameter list is
equivalent to a distinct type parameter.
A lambda expression can take another lambda expression as its argument. For more information, see "Higher-
Order Lambda Expressions" in the topic Examples of Lambda Expressions.
Because a parameter list is optional, you can omit the empty parentheses if you do not pass arguments to the
lambda expression and its lambda-declarator does not contain exception-specification, trailing-return-type, or
mutable .
Mutable Specification
Typically, a lambda's function call operator is const-by-value, but use of the mutable keyword cancels this out. It
does not produce mutable data members. The mutable specification enables the body of a lambda expression to
modify variables that are captured by value. Some of the examples later in this article show how to use mutable
.
Exception Specification
You can use the noexcept exception specification to indicate that the lambda expression does not throw any
exceptions. As with ordinary functions, the Microsoft C++ compiler generates warning C4297 if a lambda
expression declares the noexcept exception specification and the lambda body throws an exception, as shown
here:
// throw_lambda_expression.cpp
// compile with: /W4 /EHsc
int main() // C4297 expected
{
[]() noexcept { throw 5; }();
}
A lambda expression can produce another lambda expression as its return value. For more information, see
"Higher-Order Lambda Expressions" in Examples of Lambda Expressions.
Lambda Body
The lambda body (compound-statement in the Standard syntax) of a lambda expression can contain anything
that the body of an ordinary method or function can contain. The body of both an ordinary function and a
lambda expression can access these kinds of variables:
Captured variables from the enclosing scope, as described previously.
Parameters
Locally-declared variables
Class data members, when declared inside a class and this is captured
Any variable that has static storage duration—for example, global variables
The following example contains a lambda expression that explicitly captures the variable n by value and
implicitly captures the variable m by reference:
// captures_lambda_expression.cpp
// compile with: /W4 /EHsc
#include <iostream>
using namespace std;
int main()
{
int m = 0;
int n = 0;
[&, n] (int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;
}
5
0
Because the variable n is captured by value, its value remains 0 after the call to the lambda expression. The
mutable specification allows n to be modified within the lambda.
Although a lambda expression can only capture variables that have automatic storage duration, you can use
variables that have static storage duration in the body of a lambda expression. The following example uses the
generate function and a lambda expression to assign a value to each element in a vector object. The lambda
expression modifies the static variable to generate the value of the next element.
void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;
void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;
int main()
{
// The number of elements in the vector.
const int elementCount = 9;
int y = 32;
auto answer = [y]() constexpr
{
int x = 10;
return y + x;
};
A lambda is implicitly constexpr if its result satisfies the requirements of a constexpr function:
If a lambda is implicitly or explicitly constexpr , conversion to a function pointer produces a constexpr function:
Microsoft-specific
Lambdas are not supported in the following common language runtime (CLR) managed entities: ref class ,
ref struct , value class , or value struct .
If you are using a Microsoft-specific modifier such as __declspec , you can insert it into a lambda expression
immediately after the parameter-declaration-clause —for example:
To determine whether a modifier is supported by lambdas, see the article about it in the Microsoft-Specific
Modifiers section of the documentation.
In addition to C++11 Standard lambda functionality, Visual Studio supports stateless lambdas, which are omni-
convertible to function pointers that use arbitrary calling conventions.
See also
C++ Language Reference
Function Objects in the C++ Standard Library
Function Call
for_each
Lambda Expression Syntax
6/2/2021 • 4 minutes to read • Edit Online
This article demonstrates the syntax and structural elements of lambda expressions. For a description of lambda
expressions, see Lambda Expressions.
int main()
{
// Create a vector object that contains 9 elements.
vector<int> v;
for (int i = 1; i < 10; ++i) {
v.push_back(i);
}
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector.
Comments
In the example, the third argument to the for_each function is a lambda. The [&evenCount] part specifies the
capture clause of the expression, (int n) specifies the parameter list, and remaining part specifies the body of
the expression.
// even_functor.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
class FunctorClass
{
public:
// The required constructor for this example.
explicit FunctorClass(int& evenCount)
: m_evenCount(evenCount) { }
if (n % 2 == 0) {
cout << " is even " << endl;
++m_evenCount;
} else {
cout << " is odd " << endl;
}
}
private:
// Default assignment operator to silence warning C4512.
FunctorClass& operator=(const FunctorClass&);
int main()
{
// Create a vector object that contains 9 elements.
vector<int> v;
for (int i = 1; i < 10; ++i) {
v.push_back(i);
}
See also
Lambda Expressions
Examples of Lambda Expressions
generate
generate_n
for_each
Exception Specifications (throw)
Compiler Warning (level 1) C4297
Microsoft-Specific Modifiers
Examples of Lambda Expressions
3/6/2021 • 9 minutes to read • Edit Online
This article shows how to use lambda expressions in your programs. For an overview of lambda expressions,
see Lambda Expressions. For more information about the structure of a lambda expression, see Lambda
Expression Syntax.
// declaring_lambda_expressions1.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>
int main()
{
// Assign the lambda expression that adds two numbers to an auto variable.
auto f1 = [](int x, int y) { return x + y; };
Output
5
7
Remarks
For more information, see auto , function Class, and Function Call.
Although lambda expressions are most often declared in the body of a function, you can declare them anywhere
that you can initialize a variable.
Example 2
The Microsoft C++ compiler binds a lambda expression to its captured variables when the expression is
declared instead of when the expression is called. The following example shows a lambda expression that
captures the local variable i by value and the local variable j by reference. Because the lambda expression
captures i by value, the reassignment of i later in the program does not affect the result of the expression.
However, because the lambda expression captures j by reference, the reassignment of j does affect the result
of the expression.
Code
// declaring_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>
int main()
{
using namespace std;
int i = 3;
int j = 5;
Output
47
// calling_lambda_expressions1.cpp
// compile with: /EHsc
#include <iostream>
int main()
{
using namespace std;
int n = [] (int x, int y) { return x + y; }(5, 4);
cout << n << endl;
}
Output
9
Example 2
This example passes a lambda expression as an argument to the find_if function. The lambda expression
returns true if its parameter is an even number.
Code
// calling_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <list>
#include <algorithm>
#include <iostream>
int main()
{
using namespace std;
Output
Remarks
For more information about the find_if function, see find_if . For more information about the C++ Standard
Library functions that perform common algorithms, see <algorithm> .
[In This Article]
int main()
{
using namespace std;
Output
13
Remarks
In this example, [](int y) { return y * 2; } is the nested lambda expression.
[In This Article]
int main()
{
using namespace std;
Output
30
// capture "this" by value (Visual Studio 2017 version 15.3 and later)
void ApplyScale2(const vector<int>& v) const
{
for_each(v.begin(), v.end(),
[*this](int n) { cout << n * _scale << endl; });
}
The following example shows the Scale class, which encapsulates a scale value.
// function_lambda_expression.cpp
// compile with: /EHsc /W4
#include <algorithm>
#include <iostream>
#include <vector>
class Scale
{
public:
// The constructor.
explicit Scale(int scale) : _scale(scale) {}
private:
int _scale;
};
int main()
{
vector<int> values;
values.push_back(1);
values.push_back(2);
values.push_back(3);
values.push_back(4);
3
6
9
12
Remarks
The ApplyScale function uses a lambda expression to print the product of the scale value and each element in a
vector object. The lambda expression implicitly captures this so that it can access the _scale member.
// template_lambda_expression.cpp
// compile with: /EHsc
#include <vector>
#include <algorithm>
#include <iostream>
// Negates each element in the vector object. Assumes signed data type.
template <typename T>
void negate_all(vector<T>& v)
{
for_each(v.begin(), v.end(), [](T& n) { n = -n; });
}
int main()
{
// Create a vector of signed integers with a few elements.
vector<int> v;
v.push_back(34);
v.push_back(-43);
v.push_back(56);
print_all(v);
negate_all(v);
cout << "After negate_all():" << endl;
print_all(v);
}
Output
34
-43
56
After negate_all():
-34
43
-56
Remarks
For more information about C++ templates, see Templates.
[In This Article]
Handling Exceptions
Example
The body of a lambda expression follows the rules for both structured exception handling (SEH) and C++
exception handling. You can handle a raised exception in the body of a lambda expression or defer exception
handling to the enclosing scope. The following example uses the for_each function and a lambda expression to
fill a vector object with the values of another one. It uses a try / catch block to handle invalid access to the
first vector.
Code
// eh_lambda_expression.cpp
// compile with: /EHsc /W4
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
// Create a vector that contains 3 elements.
vector<int> elements(3);
Output
Caught 'invalid vector<T> subscript'.
Remarks
For more information about exception handling, see Exception Handling.
[In This Article]
// managed_lambda_expression.cpp
// compile with: /clr
using namespace System;
int main()
{
char ch = '!'; // a local unmanaged variable
Output
Hello!
Remarks
You can also use lambda expressions with the STL/CLR library. For more information, see STL/CLR Library
Reference.
IMPORTANT
Lambdas are not supported in these common language runtime (CLR) managed entities: ref class , ref struct ,
value class , and value struct .
See also
Lambda Expressions
Lambda Expression Syntax
auto
function Class
find_if
<algorithm>
Function Call
Templates
Exception Handling
STL/CLR Library Reference
constexpr lambda expressions in C++
3/6/2021 • 2 minutes to read • Edit Online
Visual Studio 2017 version 15.3 and later (available with /std:c++17): A lambda expression may be
declared as constexpr or used in a constant expression when the initialization of each data member that it
captures or introduces is allowed within a constant expression.
int y = 32;
auto answer = [y]() constexpr
{
int x = 10;
return y + x;
};
A lambda is implicitly constexpr if its result satisfies the requirements of a constexpr function:
If a lambda is implicitly or explicitly constexpr , and you convert it to a function pointer, the resulting function is
also constexpr :
See also
C++ Language Reference
Function Objects in the C++ Standard Library
Function Call
for_each
Arrays (C++)
3/6/2021 • 11 minutes to read • Edit Online
An array is a sequence of objects of the same type that occupy a contiguous area of memory. Traditional C-style
arrays are the source of many bugs, but are still common, especially in older code bases. In modern C++, we
strongly recommend using std::vector or std::array instead of C-style arrays described in this section. Both of
these standard library types store their elements as a contiguous block of memory. However, they provide much
greater type safety, and support iterators that are guaranteed to point to a valid location within the sequence.
For more information, see Containers.
Stack declarations
In a C++ array declaration, the array size is specified after the variable name, not after the type name as in some
other languages. The following example declares an array of 1000 doubles to be allocated on the stack. The
number of elements must be supplied as an integer literal or else as a constant expression. That's because the
compiler has to know how much stack space to allocate; it can't use a value computed at run-time. Each element
in the array is assigned a default value of 0. If you don't assign a default value, each element initially contains
whatever random values happen to be at that memory location.
The first element in the array is the zeroth element. The last element is the (n-1) element, where n is the number
of elements the array can contain. The number of elements in the declaration must be of an integral type and
must be greater than 0. It is your responsibility to ensure that your program never passes a value to the
subscript operator that is greater than (size - 1) .
A zero-sized array is legal only when the array is the last field in a struct or union and when the Microsoft
extensions are enabled ( /Za or /permissive- isn't set).
Stack-based arrays are faster to allocate and access than heap-based arrays. However, stack space is limited. The
number of array elements can't be so large that it uses up too much stack memory. How much is too much
depends on your program. You can use profiling tools to determine whether an array is too large.
Heap declarations
You may require an array that's too large to allocate on the stack, or whose size isn't known at compile time. It's
possible to allocate this array on the heap by using a new[] expression. The operator returns a pointer to the
first element. The subscript operator works on the pointer variable the same way it does on a stack-based array.
You can also use pointer arithmetic to move the pointer to any arbitrary elements in the array. It's your
responsibility to ensure that:
you always keep a copy of the original pointer address so that you can delete the memory when you no
longer need the array.
you don't increment or decrement the pointer address past the array bounds.
The following example shows how to define an array on the heap at run time. It shows how to access the array
elements using the subscript operator and by using pointer arithmetic:
void do_something(size_t size)
{
// Declare an array of doubles to be allocated on the heap
double* numbers = new double[size]{ 0 };
// Alternate method:
// Reset p to numbers[0]:
p = numbers;
}
int main()
{
do_something(108);
}
Initializing arrays
You can initialize an array in a loop, one element at a time, or in a single statement. The contents of the following
two arrays are identical:
int a[10];
for (int i = 0; i < 10; ++i)
{
a[i] = i + 1;
}
int b[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Declare and define the array parameter p as const to make it read-only within the function block:
The same function can also be declared in these ways, with no change in behavior. The array is still passed as a
pointer to the first element:
// Unsized array
void process(const double p[], const size_t len);
Multidimensional arrays
Arrays constructed from other arrays are multidimensional arrays. These multidimensional arrays are specified
by placing multiple bracketed constant expressions in sequence. For example, consider this declaration:
int i2[5][7];
It specifies an array of type int , conceptually arranged in a two-dimensional matrix of five rows and seven
columns, as shown in the following figure:
Conceptual layout of a multi-dimensional array
You can declare multidimensioned arrays that have an initializer list (as described in Initializers). In these
declarations, the constant expression that specifies the bounds for the first dimension can be omitted. For
example:
// arrays2.cpp
// compile with: /c
const int cMarkets = 4;
// Declare a float that represents the transportation costs.
double TransportCosts[][cMarkets] = {
{ 32.19, 47.29, 31.99, 19.11 },
{ 11.29, 22.49, 33.47, 17.29 },
{ 41.97, 22.09, 9.76, 22.55 }
};
The preceding declaration defines an array that is three rows by four columns. The rows represent factories and
the columns represent markets to which the factories ship. The values are the transportation costs from the
factories to the markets. The first dimension of the array is left out, but the compiler fills it in by examining the
initializer.
Use of the indirection operator (*) on an n-dimensional array type yields an n-1 dimensional array. If n is 1, a
scalar (or array element) is yielded.
C++ arrays are stored in row-major order. Row-major order means the last subscript varies the fastest.
Example
You can also omit the bounds specification for the first dimension of a multidimensional array in function
declarations, as shown here:
// multidimensional_arrays.cpp
// compile with: /EHsc
// arguments: 3
#include <limits> // Includes DBL_MAX
#include <iostream>
if (argv[1] == 0) {
cout << "You must specify the number of markets." << endl;
exit(0);
}
MinCost = FindMinToMkt( *argv[1] - '0', TransportCosts, cFacts);
cout << "The minimum cost to Market " << argv[1] << " is: "
<< MinCost << "\n";
}
return MinCost;
}
The function FindMinToMkt is written such that adding new factories doesn't require any code changes, just a
recompilation.
Initializing Arrays
Arrays of objects that have a class constructor are initialized by the constructor. When there are fewer items in
the initializer list than elements in the array, the default constructor is used for the remaining elements. If no
default constructor is defined for the class, the initializer list must be complete, that is, there must be one
initializer for each element in the array.
Consider the Point class that defines two constructors:
// initializing_arrays1.cpp
class Point
{
public:
Point() // Default constructor.
{
}
Point( int, int ) // Construct from two ints
{
}
};
int main()
{
}
The first element of aPoint is constructed using the constructor Point( int, int ) ; the remaining two
elements are constructed using the default constructor.
Static member arrays (whether const or not) can be initialized in their definitions (outside the class
declaration). For example:
// initializing_arrays2.cpp
class WindowColors
{
public:
static const char *rgszWindowPartList[7];
};
// using_arrays.cpp
int main() {
char chArray[10];
char *pch = chArray; // Evaluates to a pointer to the first element.
char ch = chArray[0]; // Evaluates to the value of the first element.
ch = chArray[3]; // Evaluates to the value of the fourth element.
}
When you use multidimensional arrays, you can use various combinations in expressions.
// using_arrays_2.cpp
// compile with: /EHsc /W1
#include <iostream>
using namespace std;
int main() {
double multi[4][4][3]; // Declare the array.
double (*p2multi)[3];
double (*p1multi);
In the preceding code, multi is a three-dimensional array of type double . The p2multi pointer points to an
array of type double of size three. In this example, the array is used with one, two, and three subscripts.
Although it's more common to specify all subscripts, as in the cout statement, sometimes it's useful to select a
specific subset of array elements, as shown in the statements that follow cout .
As in all addition that involves pointer types, scaling is done automatically to adjust for the size of the type. The
resultant value isn't n bytes from the origin of array_name ; instead, it's the nth element of the array. For more
information about this conversion, see Additive operators.
Similarly, for multidimensional arrays, the address is derived using the following method:
((array_name) + (subscript1 * max2 * max3 * ... * maxn) + (subscript2 * max3 * ... * maxn) + ... +
subscriptn))
Arrays in Expressions
When an identifier of an array type appears in an expression other than sizeof , address-of ( & ), or initialization
of a reference, it's converted to a pointer to the first array element. For example:
The pointer psz points to the first element of the array szError1 . Arrays, unlike pointers, aren't modifiable l-
values. That's why the following assignment is illegal:
szError1 = psz;
See also
std::array
References (C++)
3/6/2021 • 2 minutes to read • Edit Online
A reference, like a pointer, stores the address of an object that is located elsewhere in memory. Unlike a pointer,
a reference after it is initialized cannot be made to refer to a different object or set to null. There are two kinds of
references: lvalue references which refer to a named variable and rvalue references which refer to a temporary
object. The & operator signifies an lvalue reference and the && operator signifies either an rvalue reference, or
a universal reference (either rvalue or lvalue) depending on the context.
References may be declared using the following syntax:
Any valid declarator specifying a reference may be used. Unless the reference is a reference to function or array
type, the following simplified syntax applies:
int &i;
int &i, &j;
Example
// references.cpp
#include <stdio.h>
struct S {
short i;
};
int main() {
S s; // Declare the object.
S& SRef = s; // Declare the reference.
s.i = 3;
printf_s("%d\n", s.i);
printf_s("%d\n", SRef.i);
SRef.i = 4;
printf_s("%d\n", s.i);
printf_s("%d\n", SRef.i);
}
3
3
4
4
See also
Reference-Type Function Arguments
Reference-Type Function Returns
References to Pointers
Lvalue Reference Declarator: &
3/6/2021 • 2 minutes to read • Edit Online
Syntax
type-id & cast-expression
Remarks
You can think of an lvalue reference as another name for an object. An lvalue reference declaration consists of an
optional list of specifiers followed by a reference declarator. A reference must be initialized and cannot be
changed.
Any object whose address can be converted to a given pointer type can also be converted to the similar
reference type. For example, any object whose address can be converted to type char * can also be converted
to type char & .
Do not confuse reference declarations with use of the address-of operator. When the & identifier is preceded by
a type, such as int or char , identifier is declared as a reference to the type. When & identifier is not preceded
by a type, the usage is that of the address-of operator.
Example
The following example demonstrates the reference declarator by declaring a Person object and a reference to
that object. Because rFriend is a reference to myFriend , updating either variable changes the same object.
// reference_declarator.cpp
// compile with: /EHsc
// Demonstrates the reference declarator.
#include <iostream>
using namespace std;
struct Person
{
char* Name;
short Age;
};
int main()
{
// Declare a Person object.
Person myFriend;
Bill is 40
See also
References
Reference-Type Function Arguments
Reference-Type Function Returns
References to Pointers
Rvalue Reference Declarator: &&
3/6/2021 • 12 minutes to read • Edit Online
Syntax
type-id && cast-expression
Remarks
Rvalue references enable you to distinguish an lvalue from an rvalue. Lvalue references and rvalue references
are syntactically and semantically similar, but they follow somewhat different rules. For more information about
lvalues and rvalues, see Lvalues and Rvalues. For more information about lvalue references, see Lvalue
Reference Declarator: &.
The following sections describe how rvalue references support the implementation of move semantics and
perfect forwarding.
Move Semantics
Rvalue references support the implementation of move semantics, which can significantly increase the
performance of your applications. Move semantics enables you to write code that transfers resources (such as
dynamically allocated memory) from one object to another. Move semantics works because it enables resources
to be transferred from temporary objects that cannot be referenced elsewhere in the program.
To implement move semantics, you typically provide a move constructor, and optionally a move assignment
operator (operator= ), to your class. Copy and assignment operations whose sources are rvalues then
automatically take advantage of move semantics. Unlike the default copy constructor, the compiler does not
provide a default move constructor. For more information about how to write a move constructor and how to
use it in your application, see Move Constructors and Move Assignment Operators (C++).
You can also overload ordinary functions and operators to take advantage of move semantics. Visual Studio
2010 introduces move semantics into the C++ Standard Library. For example, the string class implements
operations that perform move semantics. Consider the following example that concatenates several strings and
prints the result:
// string_concatenation.cpp
// compile with: /EHsc
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = string("h") + "e" + "ll" + "o";
cout << s << endl;
}
Before Visual Studio 2010, each call to operator+ allocates and returns a new temporary string object (an
rvalue). operator+ cannot append one string to the other because it does not know whether the source strings
are lvalues or rvalues. If the source strings are both lvalues, they might be referenced elsewhere in the program
and therefore must not be modified. By using rvalue references, operator+ can be modified to take rvalues,
which cannot be referenced elsewhere in the program. Therefore, operator+ can now append one string to
another. This can significantly reduce the number of dynamic memory allocations that the string class must
perform. For more information about the string class, see basic_string Class.
Move semantics also helps when the compiler cannot use Return Value Optimization (RVO) or Named Return
Value Optimization (NRVO). In these cases, the compiler calls the move constructor if the type defines it.
To better understand move semantics, consider the example of inserting an element into a vector object. If the
capacity of the vector object is exceeded, the vector object must reallocate memory for its elements and then
copy each element to another memory location to make room for the inserted element. When an insertion
operation copies an element, it creates a new element, calls the copy constructor to copy the data from the
previous element to the new element, and then destroys the previous element. Move semantics enables you to
move objects directly without having to perform expensive memory allocation and copy operations.
To take advantage of move semantics in the vector example, you can write a move constructor to move data
from one object to another.
For more information about the introduction of move semantics into the C++ Standard Library in Visual Studio
2010, see C++ Standard Library.
Perfect Forwarding
Perfect forwarding reduces the need for overloaded functions and helps avoid the forwarding problem. The
forwarding problem can occur when you write a generic function that takes references as its parameters and it
passes (or forwards) these parameters to another function. For example, if the generic function takes a
parameter of type const T& , then the called function cannot modify the value of that parameter. If the generic
function takes a parameter of type T& , then the function cannot be called by using an rvalue (such as a
temporary object or integer literal).
Ordinarily, to solve this problem, you must provide overloaded versions of the generic function that take both
T& and const T& for each of its parameters. As a result, the number of overloaded functions increases
exponentially with the number of parameters. Rvalue references enable you to write one version of a function
that accepts arbitrary arguments and forwards them to another function as if the other function had been called
directly.
Consider the following example that declares four types, W , X , Y , and Z . The constructor for each type takes
a different combination of const and non- const lvalue references as its parameters.
struct W
{
W(int&, int&) {}
};
struct X
{
X(const int&, int&) {}
};
struct Y
{
Y(int&, const int&) {}
};
struct Z
{
Z(const int&, const int&) {}
};
Suppose you want to write a generic function that generates objects. The following example shows one way to
write this function:
int a = 4, b = 5;
W* pw = factory<W>(a, b);
However, the following example does not contain a valid call to the factory function because factory takes
lvalue references that are modifiable as its parameters, but it is called by using rvalues:
Z* pz = factory<Z>(2, 2);
Ordinarily, to solve this problem, you must create an overloaded version of the factory function for every
combination of A& and const A& parameters. Rvalue references enable you to write one version of the
factory function, as shown in the following example:
This example uses rvalue references as the parameters to the factory function. The purpose of the std::forward
function is to forward the parameters of the factory function to the constructor of the template class.
The following example shows the main function that uses the revised factory function to create instances of
the W , X , Y , and Z classes. The revised factory function forwards its parameters (either lvalues or rvalues)
to the appropriate class constructor.
int main()
{
int a = 4, b = 5;
W* pw = factory<W>(a, b);
X* px = factory<X>(2, b);
Y* py = factory<Y>(a, 2);
Z* pz = factory<Z>(2, 2);
delete pw;
delete px;
delete py;
delete pz;
}
// reference-overload.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
void f(MemoryBlock&&)
{
cout << "In f(MemoryBlock&&). This version can modify the parameter." << endl;
}
int main()
{
MemoryBlock block;
f(block);
f(MemoryBlock());
}
In this example, the first call to f passes a local variable (an lvalue) as its argument. The second call to f
passes a temporary object as its argument. Because the temporary object cannot be referenced elsewhere in the
program, the call binds to the overloaded version of f that takes an rvalue reference, which is free to modify
the object.
The compiler treats a named r value reference as an lvalue and an unnamed r value reference as an
r value.
When you write a function that takes an rvalue reference as its parameter, that parameter is treated as an lvalue
in the body of the function. The compiler treats a named rvalue reference as an lvalue because a named object
can be referenced by several parts of a program; it would be dangerous to allow multiple parts of a program to
modify or remove resources from that object. For example, if multiple parts of a program try to transfer
resources from the same object, only the first part will successfully transfer the resource.
The following example shows the function g , which is overloaded to take an lvalue reference and an rvalue
reference. The function f takes an rvalue reference as its parameter (a named rvalue reference) and returns an
rvalue reference (an unnamed rvalue reference). In the call to g from f , overload resolution selects the
version of g that takes an lvalue reference because the body of f treats its parameter as an lvalue. In the call
to g from main , overload resolution selects the version of g that takes an rvalue reference because f
returns an rvalue reference.
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
int main()
{
g(f(MemoryBlock()));
}
In g(const MemoryBlock&).
In g(MemoryBlock&&).
In this example, the main function passes an rvalue to f . The body of f treats its named parameter as an
lvalue. The call from f to g binds the parameter to an lvalue reference (the first overloaded version of g ).
You can cast an lvalue to an r value reference.
The C++ Standard Library std::move function enables you to convert an object to an rvalue reference to that
object. Alternatively, you can use the static_cast keyword to cast an lvalue to an rvalue reference, as shown in
the following example:
// cast-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
int main()
{
MemoryBlock block;
g(block);
g(static_cast<MemoryBlock&&>(block));
}
In g(const MemoryBlock&).
In g(MemoryBlock&&).
Function templates deduce their template argument types and then use reference collapsing rules.
It is common to write a function template that passes (or forwards) its parameters to another function. It is
important to understand how template type deduction works for function templates that take rvalue references.
If the function argument is an rvalue, the compiler deduces the argument to be an rvalue reference. For
example, if you pass an rvalue reference to an object of type X to a template function that takes type T&& as its
parameter, template argument deduction deduces T to be X . Therefore, the parameter has type X&& . If the
function argument is an lvalue or const lvalue, the compiler deduces its type to be an lvalue reference or
const lvalue reference of that type.
The following example declares one structure template and then specializes it for various reference types. The
print_type_and_value function takes an rvalue reference as its parameter and forwards it to the appropriate
specialized version of the S::print method. The main function demonstrates the various ways to call the
S::print method.
// template-type-deduction.cpp
// Compile with: /EHsc
#include <iostream>
#include <string>
using namespace std;
int main()
{
// The following call resolves to:
// print_type_and_value<string&>(string& && t)
// Which collapses to:
// print_type_and_value<string&>(string& t)
string s1("first");
print_type_and_value(s1);
print<T&>: first
print<const T&>: second
print<T&&>: third
print<const T&&>: fourth
To resolve each call to the print_type_and_value function, the compiler first performs template argument
deduction. The compiler then applies reference collapsing rules when it substitutes the deduced template
arguments for the parameter types. For example, passing the local variable s1 to the print_type_and_value
function causes the compiler to produce the following function signature:
print_type_and_value<string&>(string& && t)
The compiler uses reference collapsing rules to reduce the signature to the following:
print_type_and_value<string&>(string& t)
This version of the print_type_and_value function then forwards its parameter to the correct specialized version
of the S::print method.
The following table summarizes the reference collapsing rules for template argument type deduction:
Template argument deduction is an important element of implementing perfect forwarding. The section Perfect
Forwarding, which is presented earlier in this topic, describes perfect forwarding in more detail.
Summary
Rvalue references distinguish lvalues from rvalues. They can help you improve the performance of your
applications by eliminating the need for unnecessary memory allocations and copy operations. They also enable
you to write one version of a function that accepts arbitrary arguments and forwards them to another function
as if the other function had been called directly.
See also
Expressions with Unary Operators
Lvalue Reference Declarator: &
Lvalues and Rvalues
Move Constructors and Move Assignment Operators (C++)
C++ Standard Library
Reference-Type Function Arguments
3/6/2021 • 2 minutes to read • Edit Online
It is often more efficient to pass references, rather than large objects, to functions. This allows the compiler to
pass the address of the object while maintaining the syntax that would have been used to access the object.
Consider the following example that uses the Date structure:
// reference_type_function_arguments.cpp
#include <iostream>
struct Date
{
short Month;
short Day;
short Year;
};
// Add in year.
dateOfYear *= 10000;
dateOfYear += date.Year;
return dateOfYear;
}
int main()
{
Date date{ 8, 27, 2018 };
long dateOfYear = DateOfYear(date);
std::cout << dateOfYear << std::endl;
}
The preceding code shows that members of a structure passed by reference are accessed using the member-
selection operator (.) instead of the pointer member-selection operator (-> ).
Although arguments passed as reference types observe the syntax of non-pointer types, they retain one
important characteristic of pointer types: they are modifiable unless declared as const . Because the intent of
the preceding code is not to modify the object date , a more appropriate function prototype is:
long DateOfYear( const Date& date );
This prototype guarantees that the function DateOfYear will not change its argument.
Any function prototyped as taking a reference type can accept an object of the same type in its place because
there is a standard conversion from typename to typename& .
See also
References
Reference-Type Function Returns
3/6/2021 • 2 minutes to read • Edit Online
Functions can be declared to return a reference type. There are two reasons to make such a declaration:
The information being returned is a large enough object that returning a reference is more efficient than
returning a copy.
The type of the function must be an l-value.
The referred-to object will not go out of scope when the function returns.
Just as it can be more efficient to pass large objects to functions by reference, it also can be more efficient to
return large objects from functions by reference. Reference-return protocol eliminates the necessity of copying
the object to a temporary location prior to returning.
Reference-return types can also be useful when the function must evaluate to an l-value. Most overloaded
operators fall into this category, particularly the assignment operator. Overloaded operators are covered in
Overloaded Operators.
Example
Consider the Point example:
// refType_function_returns.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Point
{
public:
// Define "accessor" functions as
// reference types.
unsigned& x();
unsigned& y();
private:
// Note that these are declared at class scope:
unsigned obj_x;
unsigned obj_y;
};
int main()
{
Point ThePoint;
// Use x() and y() as l-values.
ThePoint.x() = 7;
ThePoint.y() = 9;
Output
x = 7
y = 9
Notice that the functions x and y are declared as returning reference types. These functions can be used on
either side of an assignment statement.
Note also that in main, ThePoint object remains in scope, and therefore its reference members are still alive and
can be safely accessed.
Declarations of reference types must contain initializers except in the following cases:
Explicit extern declaration
Declaration of a class member
Declaration within a class
Declaration of an argument to a function or the return type for a function
Caution returning address of local
If you declare an object at local scope, that object will be destroyed when the function returns. If the function
returns a reference to that object, that reference will probably cause an access violation at runtime if the caller
attempts to use the null reference.
The compiler issues a warning in this case: warning C4172: returning address of local variable or temporary . In
simple programs it is possible that occasionally no access violation will occur if the reference is accessed by the
caller before the memory location is overwritten. This is due to sheer luck. Heed the warning.
See also
References
References to pointers
3/6/2021 • 2 minutes to read • Edit Online
References to pointers can be declared in much the same way as references to objects. A reference to a pointer
is a modifiable value that's used like a normal pointer.
Example
This code sample shows the difference between using a pointer to a pointer and a reference to a pointer.
Functions Add1 and Add2 are functionally equivalent, although they're not called the same way. The difference
is that Add1 uses double indirection, but Add2 uses the convenience of a reference to a pointer.
// references_to_pointers.cpp
// compile with: /EHsc
#include <iostream>
#include <string>
enum {
sizeOfBuffer = 132
};
if ( strlen( szBuf ) ) {
switch ( *argv[1] ) {
// Method 1: Use double indirection.
case '1':
Add1( &btRoot, szBuf );
break;
// Method 2: Use reference to a pointer.
case '2':
Add2( btRoot, szBuf );
break;
default:
cerr << "Illegal value '"
<< *argv[1]
<< "' supplied for add method.\n"
<< "Choose 1 or 2.\n";
return -1;
}
}
}
// Display the sorted list.
PrintTree( btRoot );
}
Usage: references_to_pointers.exe [1 | 2]
where:
1 uses double indirection
2 uses a reference to a pointer.
See also
References
Pointers (C++)
3/27/2020 • 2 minutes to read • Edit Online
A pointer is a variable that stores the memory address of an object. Pointers are used extensively in both C and
C++ for three main purposes:
to allocate new objects on the heap,
to pass functions to other functions
to iterate over elements in arrays or other data structures.
In C-style programming, raw pointers are used for all these scenarios. However, raw pointers are the source of
many serious programming errors. Therefore, their use is strongly discouraged except where they provide a
significant performance benefit and there is no ambiguity as to which pointer is the owning pointer that is
responsible for deleting the object. Modern C++ provides smart pointers for allocating objects, iterators for
traversing data structures, and lambda expressions for passing functions. By using these language and library
facilities instead of raw pointers, you will make your program safer, easier to debug, and simpler to understand
and maintain. See Smart pointers, Iterators, and Lambda expressions for more information.
In this section
Raw pointers
Const and volatile pointers
new and delete operators
Smart pointers
How to: Create and use unique_ptr instances
How to: Create and use shared_ptr instances
How to: Create and use weak_ptr instances
How to: Create and use CComPtr and CComQIPtr instances
See also
Iterators
Lambda expressions
Raw pointers (C++)
11/2/2020 • 9 minutes to read • Edit Online
A pointer is a type of variable. It stores the address of an object in memory, and is used to access that object. A
raw pointer is a pointer whose lifetime is not controlled by an encapsulating object, such as a smart pointer. A
raw pointer can be assigned the address of another non-pointer variable, or it can be assigned a value of nullptr.
A pointer that hasn't been assigned a value contains random data.
A pointer can also be dereferenced to retrieve the value of the object that it points at. The member access
operator provides access to an object's members.
A pointer can point to a typed object or to void . When a program allocates an object on the heap in memory, it
receives the address of that object in the form of a pointer. Such pointers are called owning pointers. An owning
pointer (or a copy of it) must be used to explicitly free the heap-allocated object when it's no longer needed.
Failure to free the memory results in a memory leak, and renders that memory location unavailable to any other
program on the machine. Memory allocated using new must be freed by using delete (or delete[] ). For more
information, see new and delete operators.
A pointer (if it isn't declared as const ) can be incremented or decremented to point at another location in
memory. This operation is called pointer arithmetic. It's used in C-style programming to iterate over elements in
arrays or other data structures. A const pointer can't be made to point to a different memory location, and in
that sense is similar to a reference. For more information, see const and volatile pointers.
const int c = 1;
const int* pconst = &c; // declare a non-const pointer to const int
const int c2 = 2;
pconst = &c2; // OK pconst itself isn't const
const int* const pconst2 = &c;
// pconst2 = &c2; // Error! pconst2 is const.
On 64-bit operating systems, a pointer has a size of 64 bits. A system's pointer size determines how much
addressable memory it can have. All copies of a pointer point to the same memory location. Pointers (along with
references) are used extensively in C++ to pass larger objects to and from functions. That's because it's often
more efficient to copy an object's address than to copy the entire object. When defining a function, specify
pointer parameters as const unless you intend the function to modify the object. In general, const references
are the preferred way to pass objects to functions unless the value of the object can possibly be nullptr .
Pointers to functions enable functions to be passed to other functions and are used for "callbacks" in C-style
programming. Modern C++ uses lambda expressions for this purpose.
#include <iostream>
#include <string>
class MyClass
{
public:
int num;
std::string name;
void print() { std::cout << name << ":" << num << std::endl; }
};
int main()
{
// Use the * operator to declare a pointer type
// Use new to allocate and initialize memory
MyClass* pmc = new MyClass{ 108, "Nick" };
// Copy the pointer. Now pmc and pmc2 point to same object!
MyClass* pmc2 = pmc;
#include <iostream>
int main()
{
Certain arithmetic operations can be used on non-const pointers to make them point to another memory
location. Pointers are incremented and decremented using the ++ , += , -= and -- operators. This technique can
be used in arrays and is especially useful in buffers of untyped data. A void* gets incremented by the size of a
char (1 byte). A typed pointer gets incremented by size of the type it points to.
The following example demonstrates how pointer arithmetic can be used to access individual pixels in a bitmap
on Windows. Note the use of new and delete , and the dereference operator.
#include <Windows.h>
#include <fstream>
int main()
{
BITMAPINFOHEADER header;
header.biHeight = 100; // Multiple of 4 for simplicity.
header.biWidth = 100;
header.biBitCount = 24;
header.biPlanes = 1;
header.biCompression = BI_RGB;
header.biSize = sizeof(BITMAPINFOHEADER);
BITMAPFILEHEADER bf;
bf.bfType = 0x4D42;
bf.bfSize = header.biSize + 14 + bufferSize;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //54
wf.write(reinterpret_cast<char*>(&bf), sizeof(bf));
wf.write(reinterpret_cast<char*>(&header), sizeof(header));
wf.write(reinterpret_cast<char*>(begin), bufferSize);
void* pointers
A pointer to void simply points to a raw memory location. Sometimes it's necessary to use void* pointers, for
example when passing between C++ code and C functions.
When a typed pointer is cast to a void pointer, the contents of the memory location are unchanged. However, the
type information is lost, so that you can't do increment or decrement operations. A memory location can be cast,
for example, from MyClass* to void* and back again to MyClass* . Such operations are inherently error-prone
and require great care to avoid errors. Modern C++ discourages the use of void pointers in almost all
circumstances.
//func.c
void func(void* data, int length)
{
char* c = (char*)(data);
// main.cpp
#include <iostream>
extern "C"
{
void func(void* data, int length);
}
class MyClass
{
public:
int num;
std::string name;
void print() { std::cout << name << ":" << num << std::endl; }
};
int main()
{
MyClass* mc = new MyClass{10, "Marian"};
void* p = static_cast<void*>(mc);
MyClass* mc2 = static_cast<MyClass*>(p);
std::cout << mc2->name << std::endl; // "Marian"
Pointers to functions
In C-style programming, function pointers are used primarily to pass functions to other functions. This
technique allows the caller to customize the behavior of a function without modifying it. In modern C++,
lambda expressions provide the same capability with greater type safety and other advantages.
A function pointer declaration specifies the signature that the pointed-to function must have:
// Declare pointer to any function that...
The following example shows a function combine that takes as a parameter any function that accepts a
std::string and returns a std::string . Depending on the function that's passed to combine , it either prepends
or appends a string.
#include <iostream>
#include <string>
string append(string s)
{
return base.append(" ").append(s);
}
string prepend(string s)
{
return s.append(" ").append(base);
}
int main()
{
cout << combine("from MSVC", append) << "\n";
cout << combine("Good morning and", prepend) << "\n";
}
See also
Smart pointers Indirection Operator: *
Address-of Operator: &
Welcome back to C++
const and volatile pointers
3/6/2021 • 3 minutes to read • Edit Online
The const and volatile keywords change how pointers are treated. The const keyword specifies that the pointer
cannot be modified after initialization; the pointer is protected from modification thereafter.
The volatile keyword specifies that the value associated with the name that follows can be modified by actions
other than those in the user application. Therefore, the volatile keyword is useful for declaring objects in
shared memory that can be accessed by multiple processes or global data areas used for communication with
interrupt service routines.
When a name is declared as volatile , the compiler reloads the value from memory each time it is accessed by
the program. This dramatically reduces the possible optimizations. However, when the state of an object can
change unexpectedly, it is the only way to ensure predictable program performance.
To declare the object pointed to by the pointer as const or volatile , use a declaration of the form:
To declare the value of the pointer — that is, the actual address stored in the pointer — as const or volatile ,
use a declaration of the form:
The C++ language prevents assignments that would allow modification of an object or pointer declared as
const . Such assignments would remove the information that the object or pointer was declared with, thereby
violating the intent of the original declaration. Consider the following declarations:
Given the preceding declarations of two objects ( cch , of type const char , and ch , of type char) , the following
declaration/initializations are valid:
The declaration of pch2 declares a pointer through which a constant object might be modified and is therefore
disallowed. The declaration of pch3 specifies that the pointer is constant, not the object; the declaration is
disallowed for the same reason the pch2 declaration is disallowed.
The following eight assignments show assigning through pointer and changing of pointer value for the
preceding declarations; for now, assume that the initialization was correct for pch1 through pch8 .
Pointers declared as volatile , or as a mixture of const and volatile , obey the same rules.
Pointers to const objects are often used in function declarations as follows:
The preceding statement declares a function, strcpy_s, where two of the three arguments are of type pointer to
char . Because the arguments are passed by reference and not by value, the function would be free to modify
both strDestination and strSource if strSource were not declared as const . The declaration of strSource as
const assures the caller that strSource cannot be changed by the called function.
NOTE
Because there is a standard conversion from typename * to const typename * , it is legal to pass an argument of type
char * to strcpy_s. However, the reverse is not true; no implicit conversion exists to remove the const attribute from
an object or pointer.
A const pointer of a given type can be assigned to a pointer of the same type. However, a pointer that is not
const cannot be assigned to a const pointer. The following code shows correct and incorrect assignments:
// const_pointer.cpp
int *const cpObject = 0;
int *pObject;
int main() {
pObject = cpObject;
cpObject = pObject; // C3892
}
The following sample shows how to declare an object as const if you have a pointer to a pointer to an object.
// const_pointer2.cpp
struct X {
X(int i) : m_i(i) { }
int m_i;
};
int main() {
// correct
const X cx(10);
const X * pcx = &cx;
const X ** ppcx = &pcx;
// also correct
X const cx2(20);
X const * pcx2 = &cx2;
X const ** ppcx2 = &pcx2;
}
See also
Pointers Raw pointers
new and delete operators
11/2/2020 • 5 minutes to read • Edit Online
C++ supports dynamic allocation and deallocation of objects using the new and delete operators. These
operators allocate memory for objects from a pool called the free store. The new operator calls the special
function operator new , and the delete operator calls the special function operator delete .
The new function in the C++ Standard Library supports the behavior specified in the C++ standard, which is to
throw a std::bad_alloc exception if the memory allocation fails. If you still want the non-throwing version of
new , link your program with nothrownew.obj . However, when you link with nothrownew.obj , the default
operator new in the C++ Standard Library no longer functions.
For a list of the library files in the C Runtime Library and the C++ Standard Library, see CRT Library Features.
If the request is for zero bytes of storage, operator new returns a pointer to a distinct object. That is, repeated
calls to operator new return different pointers. If there's insufficient memory for the allocation request,
operator new throws a std::bad_alloc exception. Or, it returns nullptr if you've linked in non-throwing
operator new support.
You can write a routine that attempts to free memory and retry the allocation. For more information, see
_set_new_handler . For details on the recovery scheme, see the Handling insufficient memory section.
The two scopes for operator new functions are described in the following table.
Scope for operator new functions
O P ERATO R SC O P E
The first argument to operator new must be of type size_t , defined in <stddef.h>, and the return type is
always void* .
The global operator new function is called when the new operator is used to allocate objects of built-in types,
objects of class type that don't contain user-defined operator new functions, and arrays of any type. When the
new operator is used to allocate objects of a class type where an operator new is defined, that class's
operator new is called.
An operator new function defined for a class is a static member function (which can't be virtual) that hides the
global operator new function for objects of that class type. Consider the case where new is used to allocate and
set memory to a given value:
#include <malloc.h>
#include <memory.h>
class Blanks
{
public:
Blanks(){}
void *operator new( size_t stAllocateBlock, char chInit );
};
void *Blanks::operator new( size_t stAllocateBlock, char chInit )
{
void *pvTemp = malloc( stAllocateBlock );
if( pvTemp != 0 )
memset( pvTemp, chInit, stAllocateBlock );
return pvTemp;
}
// For discrete objects of type Blanks, the global operator new function
// is hidden. Therefore, the following code allocates an object of type
// Blanks and initializes it to 0xa5
int main()
{
Blanks *a5 = new(0xa5) Blanks;
return a5 != 0;
}
The argument supplied in parentheses to new is passed to Blanks::operator new as the chInit argument.
However, the global operator new function is hidden, causing code such as the following to generate an error:
The compiler supports member array new and delete operators in a class declaration. For example:
class MyClass
{
public:
void * operator new[] (size_t)
{
return 0;
}
void operator delete[] (void*)
{
}
};
int main()
{
MyClass *pMyClass = new MyClass[5];
delete [] pMyClass;
}
There's another way to handle failed memory allocation requests. Write a custom recovery routine to handle
such a failure, then register your function by calling the _set_new_handler run-time function.
There are global and class-scoped operator delete functions. Only one operator delete function can be
defined for a given class; if defined, it hides the global operator delete function. The global operator delete
function is always called for arrays of any type.
The global operator delete function. Two forms exist for the global operator delete and class-member
operator delete functions:
Only one of the preceding two forms can be present for a given class. The first form takes a single argument of
type void * , which contains a pointer to the object to deallocate. The second form, sized deallocation, takes two
arguments: the first is a pointer to the memory block to deallocate, and the second is the number of bytes to
deallocate. The return type of both forms is void ( operator delete can't return a value).
The intent of the second form is to speed up searching for the correct size category of the object to delete. This
information often isn't stored near the allocation itself, and is likely uncached. The second form is useful when an
operator delete function from a base class is used to delete an object of a derived class.
The operator delete function is static, so it can't be virtual. The operator delete function obeys access control,
as described in Member-Access Control.
The following example shows user-defined operator new and operator delete functions designed to log
allocations and deallocations of memory:
#include <iostream>
using namespace std;
free( pvMem );
}
The preceding code can be used to detect "memory leakage", that is, memory that's allocated on the free store
but never freed. To detect leaks, the global new and delete operators are redefined to count allocation and
deallocation of memory.
The compiler supports member array new and delete operators in a class declaration. For example:
// spec1_the_operator_delete_function2.cpp
// compile with: /c
class X {
public:
void * operator new[] (size_t) {
return 0;
}
void operator delete[] (void*) {}
};
void f() {
X *pX = new X[5];
delete [] pX;
}
Smart pointers (Modern C++)
3/6/2021 • 7 minutes to read • Edit Online
In modern C++ programming, the Standard Library includes smart pointers, which are used to help ensure that
programs are free of memory and resource leaks and are exception-safe.
void UseRawPointer()
{
// Using a raw pointer -- not recommended.
Song* pSong = new Song(L"Nothing on You", L"Bruno Mars");
// Use pSong...
void UseSmartPointer()
{
// Declare a smart pointer on stack and pass it the raw pointer.
unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));
// Use song2...
wstring s = song2->duration_;
//...
As shown in the example, a smart pointer is a class template that you declare on the stack, and initialize by using
a raw pointer that points to a heap-allocated object. After the smart pointer is initialized, it owns the raw pointer.
This means that the smart pointer is responsible for deleting the memory that the raw pointer specifies. The
smart pointer destructor contains the call to delete, and because the smart pointer is declared on the stack, its
destructor is invoked when the smart pointer goes out of scope, even if an exception is thrown somewhere
further up the stack.
Access the encapsulated pointer by using the familiar pointer operators, -> and * , which the smart pointer
class overloads to return the encapsulated raw pointer.
The C++ smart pointer idiom resembles object creation in languages such as C#: you create the object and then
let the system take care of deleting it at the correct time. The difference is that no separate garbage collector
runs in the background; memory is managed through the standard C++ scoping rules so that the runtime
environment is faster and more efficient.
IMPORTANT
Always create smart pointers on a separate line of code, never in a parameter list, so that a subtle resource leak won't
occur due to certain parameter list allocation rules.
The following example shows how a unique_ptr smart pointer type from the C++ Standard Library could be
used to encapsulate a pointer to a large object.
class LargeObject
{
public:
void DoSomething(){}
};
The example demonstrates the following essential steps for using smart pointers.
1. Declare the smart pointer as an automatic (local) variable. (Do not use the new or malloc expression on
the smart pointer itself.)
2. In the type parameter, specify the pointed-to type of the encapsulated pointer.
3. Pass a raw pointer to a new -ed object in the smart pointer constructor. (Some utility functions or smart
pointer constructors do this for you.)
4. Use the overloaded -> and * operators to access the object.
5. Let the smart pointer delete the object.
Smart pointers are designed to be as efficient as possible both in terms of memory and performance. For
example, the only data member in unique_ptr is the encapsulated pointer. This means that unique_ptr is
exactly the same size as that pointer, either four bytes or eight bytes. Accessing the encapsulated pointer by
using the smart pointer overloaded * and -> operators is not significantly slower than accessing the raw
pointers directly.
Smart pointers have their own member functions, which are accessed by using "dot" notation. For example,
some C++ Standard Library smart pointers have a reset member function that releases ownership of the
pointer. This is useful when you want to free the memory owned by the smart pointer before the smart pointer
goes out of scope, as shown in the following example.
void SmartPointerDemo2()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
Smart pointers usually provide a way to access their raw pointer directly. C++ Standard Library smart pointers
have a get member function for this purpose, and CComPtr has a public p class member. By providing direct
access to the underlying pointer, you can use the smart pointer to manage memory in your own code and still
pass the raw pointer to code that does not support smart pointers.
void SmartPointerDemo4()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
See also
Pointers
C++ Language Reference
C++ Standard Library
How to: Create and use unique_ptr instances
3/6/2021 • 2 minutes to read • Edit Online
A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a
function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can
only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr
and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because
multiple ownership adds complexity to the program logic. Therefore, when you need a smart pointer for a plain
C++ object, use unique_ptr , and when you construct a unique_ptr , use the make_unique helper function.
The following diagram illustrates the transfer of ownership between two unique_ptr instances.
unique_ptr is defined in the <memory> header in the C++ Standard Library. It is exactly as efficient as a raw
pointer and can be used in C++ Standard Library containers. The addition of unique_ptr instances to C++
Standard Library containers is efficient because the move constructor of the unique_ptr eliminates the need for
a copy operation.
Example 1
The following example shows how to create unique_ptr instances and pass them between functions.
void MakeSongs()
{
// Create a new unique_ptr with a new object.
auto song = make_unique<Song>(L"Mr. Children", L"Namonaki Uta");
These examples demonstrate this basic characteristic of unique_ptr : it can be moved, but not copied. "Moving"
transfers ownership to a new unique_ptr and resets the old unique_ptr .
Example 2
The following example shows how to create unique_ptr instances and use them in a vector.
void SongVector()
{
vector<unique_ptr<Song>> songs;
In the range for loop, notice that the unique_ptr is passed by reference. If you try to pass by value here, the
compiler will throw an error because the unique_ptr copy constructor is deleted.
Example 3
The following example shows how to initialize a unique_ptr that is a class member.
class MyClass
{
private:
// MyClass owns the unique_ptr.
unique_ptr<ClassFactory> factory;
public:
void MakeClass()
{
factory->DoSomething();
}
};
Example 4
You can use make_unique to create a unique_ptr to an array, but you cannot use make_unique to initialize the
array elements.
// Create a unique_ptr to an array of 5 integers.
auto p = make_unique<int[]>(5);
See also
Smart Pointers (Modern C++)
make_unique
How to: Create and Use shared_ptr instances
3/6/2021 • 6 minutes to read • Edit Online
The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more
than one owner might have to manage the lifetime of the object in memory. After you initialize a shared_ptr
you can copy it, pass it by value in function arguments, and assign it to other shared_ptr instances. All the
instances point to the same object, and share access to one "control block" that increments and decrements the
reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count
reaches zero, the control block deletes the memory resource and itself.
The following illustration shows several shared_ptr instances that point to one memory location.
Example setup
The examples that follow all assume that you've included the required headers and declared the required types,
as shown here:
// shared_ptr-examples.cpp
// The following examples assume these declarations:
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
struct MediaAsset
{
virtual ~MediaAsset() = default; // make it polymorphic
};
int main()
{
// The examples go here, in order:
// Example 1
// Example 2
// Example 3
// Example 4
// Example 6
}
Example 1
Whenever possible, use the make_shared function to create a shared_ptr when the memory resource is created
for the first time. make_shared is exception-safe. It uses the same call to allocate the memory for the control
block and the resource, which reduces the construction overhead. If you don't use make_shared , then you have
to use an explicit new expression to create the object before you pass it to the shared_ptr constructor. The
following example shows various ways to declare and initialize a shared_ptr together with a new object.
// Use make_shared function when possible.
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");
Example 2
The following example shows how to declare and initialize shared_ptr instances that take on shared ownership
of an object that has already been allocated by another shared_ptr . Assume that sp2 is an initialized
shared_ptr .
Example 3
shared_ptr is also helpful in C++ Standard Library containers when you're using algorithms that copy
elements. You can wrap elements in a shared_ptr , and then copy it into other containers with the understanding
that the underlying memory is valid as long as you need it, and no longer. The following example shows how to
use the remove_copy_if algorithm on shared_ptr instances in a vector.
vector<shared_ptr<Song>> v {
make_shared<Song>(L"Bob Dylan", L"The Times They Are A Changing"),
make_shared<Song>(L"Aretha Franklin", L"Bridge Over Troubled Water"),
make_shared<Song>(L"Thalía", L"Entre El Mar y Una Estrella")
};
vector<shared_ptr<Song>> v2;
remove_copy_if(v.begin(), v.end(), back_inserter(v2), [] (shared_ptr<Song> s)
{
return s->artist.compare(L"Bob Dylan") == 0;
});
vector<shared_ptr<MediaAsset>> assets {
make_shared<Song>(L"Himesh Reshammiya", L"Tera Surroor"),
make_shared<Song>(L"Penaz Masani", L"Tu Dil De De"),
make_shared<Photo>(L"2011-04-06", L"Redmond, WA", L"Soccer field at Microsoft.")
};
vector<shared_ptr<MediaAsset>> photos;
Example 5
You can pass a shared_ptr to another function in the following ways:
Pass the shared_ptr by value. This invokes the copy constructor, increments the reference count, and
makes the callee an owner. There's a small amount of overhead in this operation, which may be
significant depending on how many shared_ptr objects you're passing. Use this option when the implied
or explicit code contract between the caller and callee requires that the callee be an owner.
Pass the shared_ptr by reference or const reference. In this case, the reference count isn't incremented,
and the callee can access the pointer as long as the caller doesn't go out of scope. Or, the callee can decide
to create a shared_ptr based on the reference, and become a shared owner. Use this option when the
caller has no knowledge of the callee, or when you must pass a shared_ptr and want to avoid the copy
operation for performance reasons.
Pass the underlying pointer or a reference to the underlying object. This enables the callee to use the
object, but doesn't enable it to share ownership or extend the lifetime. If the callee creates a shared_ptr
from the raw pointer, the new shared_ptr is independent from the original, and doesn't control the
underlying resource. Use this option when the contract between the caller and callee clearly specifies that
the caller retains ownership of the shared_ptr lifetime.
When you're deciding how to pass a shared_ptr , determine whether the callee has to share ownership of
the underlying resource. An "owner" is an object or function that can keep the underlying resource alive
for as long as it needs it. If the caller has to guarantee that the callee can extend the life of the pointer
beyond its (the function's) lifetime, use the first option. If you don't care whether the callee extends the
lifetime, then pass by reference and let the callee copy it or not.
If you have to give a helper function access to the underlying pointer, and you know that the helper
function will just use the pointer and return before the calling function returns, then that function doesn't
have to share ownership of the underlying pointer. It just has to access the pointer within the lifetime of
the caller's shared_ptr . In this case, it's safe to pass the shared_ptr by reference, or pass the raw pointer
or a reference to the underlying object. Passing this way provides a small performance benefit, and may
also help you express your programming intent.
Sometimes, for example in a std::vector<shared_ptr<T>> , you may have to pass each shared_ptr to a
lambda expression body or named function object. If the lambda or function doesn't store the pointer,
then pass the shared_ptr by reference to avoid invoking the copy constructor for each element.
Example 6
The following example shows how shared_ptr overloads various comparison operators to enable pointer
comparisons on the memory that is owned by the shared_ptr instances.
See also
Smart Pointers (Modern C++)
How to: Create and use weak_ptr instances
3/6/2021 • 3 minutes to read • Edit Online
Sometimes an object must store a way to access the underlying object of a shared_ptr without causing the
reference count to be incremented. Typically, this situation occurs when you have cyclic references between
shared_ptr instances.
The best design is to avoid shared ownership of pointers whenever you can. However, if you must have shared
ownership of shared_ptr instances, avoid cyclic references between them. When cyclic references are
unavoidable, or even preferable for some reason, use weak_ptr to give one or more of the owners a weak
reference to another shared_ptr . By using a weak_ptr , you can create a shared_ptr that joins to an existing set
of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not
participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.
However, you can use a weak_ptr to try to obtain a new copy of the shared_ptr with which it was initialized. If
the memory has already been deleted, the weak_ptr 's bool operator returns false . If the memory is still valid,
the new shared pointer increments the reference count and guarantees that the memory will be valid as long as
the shared_ptr variable stays in scope.
Example
The following code example shows a case where weak_ptr is used to ensure proper deletion of objects that
have circular dependencies. As you examine the example, assume that it was created only after alternative
solutions were considered. The Controller objects represent some aspect of a machine process, and they
operate independently. Each controller must be able to query the status of the other controllers at any time, and
each one contains a private vector<weak_ptr<Controller>> for this purpose. Each vector contains a circular
reference, and therefore, weak_ptr instances are used instead of shared_ptr .
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
class Controller
{
public:
int Num;
wstring Status;
vector<weak_ptr<Controller>> others;
explicit Controller(int i) : Num(i), Status(L"On")
{
wcout << L"Creating Controller" << Num << endl;
}
~Controller()
{
wcout << L"Destroying Controller" << Num << endl;
}
void RunTest()
{
vector<shared_ptr<Controller>> v{
make_shared<Controller>(0),
make_shared<Controller>(1),
make_shared<Controller>(2),
make_shared<Controller>(3),
make_shared<Controller>(4),
};
int main()
{
RunTest();
wcout << L"Press any key" << endl;
char ch;
cin.getline(&ch, 1);
}
Creating Controller0
Creating Controller1
Creating Controller2
Creating Controller3
Creating Controller4
push_back to v[0]: 1
push_back to v[0]: 2
push_back to v[0]: 3
push_back to v[0]: 4
push_back to v[1]: 0
push_back to v[1]: 2
push_back to v[1]: 3
push_back to v[1]: 4
push_back to v[2]: 0
push_back to v[2]: 1
push_back to v[2]: 3
push_back to v[2]: 4
push_back to v[3]: 0
push_back to v[3]: 1
push_back to v[3]: 2
push_back to v[3]: 4
push_back to v[4]: 0
push_back to v[4]: 1
push_back to v[4]: 2
push_back to v[4]: 3
use_count = 1
Status of 1 = On
Status of 2 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 2 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 2 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 2 = On
Status of 3 = On
Destroying Controller0
Destroying Controller1
Destroying Controller2
Destroying Controller3
Destroying Controller4
Press any key
As an experiment, modify the vector others to be a vector<shared_ptr<Controller>> , and then in the output,
notice that no destructors are invoked when RunTest returns.
See also
Smart Pointers (Modern C++)
How to: Create and use CComPtr and CComQIPtr
instances
3/6/2021 • 3 minutes to read • Edit Online
In classic Windows programming, libraries are often implemented as COM objects (or more precisely, as COM
servers). Many Windows operating system components are implemented as COM servers, and many
contributors provide libraries in this form. For information about the basics of COM, see Component Object
Model (COM).
When you instantiate a Component Object Model (COM) object, store the interface pointer in a COM smart
pointer, which performs the reference counting by using calls to AddRef and Release in the destructor. If you
are using the Active Template Library (ATL) or the Microsoft Foundation Class Library (MFC), then use the
CComPtr smart pointer. If you are not using ATL or MFC, then use _com_ptr_t . Because there is no COM
equivalent to std::unique_ptr , use these smart pointers for both single-owner and multiple-owner scenarios.
Both CComPtr and ComQIPtr support move operations that have rvalue references.
Example: CComPtr
The following example shows how to use CComPtr to instantiate a COM object and obtain pointers to its
interfaces. Notice that the CComPtr::CoCreateInstance member function is used to create the COM object,
instead of the Win32 function that has the same name.
void CComPtrDemo()
{
HRESULT hr = CoInitialize(NULL);
CoUninitialize();
CComPtr and its relatives are part of the ATL and are defined in <atlcomcli.h>. _com_ptr_t is declared in
<comip.h>. The compiler creates specializations of _com_ptr_t when it generates wrapper classes for type
libraries.
Example: CComQIPt
ATL also provides CComQIPtr , which has a simpler syntax for querying a COM object to retrieve an additional
interface. However, we recommend CComPtr because it does everything that CComQIPtr can do and is
semantically more consistent with raw COM interface pointers. If you use a CComPtr to query for an interface,
the new interface pointer is placed in an out parameter. If the call fails, an HRESULT is returned, which is the
typical COM pattern. With CComQIPtr , the return value is the pointer itself, and if the call fails, the internal
HRESULT return value cannot be accessed. The following two lines show how the error handling mechanisms in
CComPtr and CComQIPtr differ.
// CComPtr with error handling:
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }
Example: IDispatch
CComPtr provides a specialization for IDispatch that enables it to store pointers to COM automation
components and invoke the methods on the interface by using late binding. CComDispatchDriver is a typedef for
CComQIPtr<IDispatch, &IIDIDispatch> , which is implicitly convertible to CComPtr<IDispatch> . Therefore, when
any of these three names appears in code, it is equivalent to CComPtr<IDispatch> . The following example shows
how to obtain a pointer to the Microsoft Word object model by using a CComPtr<IDispatch> .
void COMAutomationSmartPointerDemo()
{
CComPtr<IDispatch> pWord;
CComQIPtr<IDispatch, &IID_IDispatch> pqi = pWord;
CComDispatchDriver pDriver = pqi;
HRESULT hr;
_variant_t pOutVal;
CoInitialize(NULL);
hr = pWord.CoCreateInstance(L"Word.Application", NULL, CLSCTX_LOCAL_SERVER);
if(FAILED(hr)){ /*... handle hr error*/ }
CoUninitialize();
}
See also
Smart Pointers (Modern C++)
Pimpl For Compile-Time Encapsulation (Modern
C++)
3/6/2021 • 2 minutes to read • Edit Online
The pimpl idiom is a modern C++ technique to hide implementation, to minimize coupling, and to separate
interfaces. Pimpl is short for "pointer to implementation." You may already be familiar with the concept but
know it by other names like Cheshire Cat or Compiler Firewall idiom.
Pimpl header
// my_class.h
class my_class {
// ... all public and protected stuff goes here ...
private:
class impl; unique_ptr<impl> pimpl; // opaque type here
};
The pimpl idiom avoids rebuild cascades and brittle object layouts. It's well suited for (transitively) popular types.
Pimpl implementation
Define the impl class in the .cpp file.
// my_class.cpp
class my_class::impl { // defined privately here
// ... all private data and functions: all of these
// can now change without recompiling callers ...
};
my_class::my_class(): pimpl( new impl )
{
// ... set impl values ...
}
Best practices
Consider whether to add support for non-throwing swap specialization.
See also
Welcome back to C++
C++ Language Reference
C++ Standard Library
Exception handling in MSVC
4/15/2020 • 2 minutes to read • Edit Online
An exception is an error condition, possibly outside the program's control, that prevents the program from
continuing along its regular execution path. Certain operations, including object creation, file input/output, and
function calls made from other modules, are all potential sources of exceptions, even when your program is
running correctly. Robust code anticipates and handles exceptions. To detect logic errors, use assertions rather
than exceptions (see Using Assertions).
Kinds of exceptions
The Microsoft C++ compiler (MSVC) supports three kinds of exception handling:
C++ exception handling
For most C++ programs, you should use C++ exception handling. It's type-safe, and ensures that object
destructors are invoked during stack unwinding.
Structured exception handling
Windows supplies its own exception mechanism, called structured exception handling (SEH). It's not
recommended for C++ or MFC programming. Use SEH only in non-MFC C programs.
MFC exceptions
Since version 3.0, MFC has used C++ exceptions. It still supports its older exception handling macros,
which are similar to C++ exceptions in form. For advice about mixing MFC macros and C++ exceptions,
see Exceptions: Using MFC Macros and C++ Exceptions.
Use an /EH compiler option to specify the exception handling model to use in a C++ project. Standard C++
exception handling (/EHsc ) is the default in new C++ projects in Visual Studio.
We don't recommend you mix the exception handling mechanisms. For example, don't use C++ exceptions with
structured exception handling. Using C++ exception handling exclusively makes your code more portable, and it
allows you to handle exceptions of any type. For more information about the drawbacks of structured exception
handling, see Structured Exception Handling.
In this section
Modern C++ best practices for exceptions and error handling
How to design for exception safety
How to interface between exceptional and non-exceptional code
The try, catch, and throw Statements
How Catch Blocks are Evaluated
Exceptions and Stack Unwinding
Exception Specifications
noexcept
Unhandled C++ Exceptions
Mixing C (Structured) and C++ Exceptions
Structured Exception Handling (SEH) (C/C++)
See also
C++ Language Reference
x64 exception handling
Exception Handling (C++/CLI and C++/CX)
Modern C++ best practices for exceptions and error
handling
11/2/2020 • 6 minutes to read • Edit Online
In modern C++, in most scenarios, the preferred way to report and handle both logic errors and runtime errors
is to use exceptions. It's especially true when the stack might contain several function calls between the function
that detects the error, and the function that has the context to handle the error. Exceptions provide a formal, well-
defined way for code that detects errors to pass the information up the call stack.
void MyFunc(int c)
{
if (c > numeric_limits< char> ::max())
throw invalid_argument("MyFunc argument too large.");
//...
}
int main()
{
try
{
MyFunc(256); //cause an exception to throw
}
catch (invalid_argument& e)
{
cerr << e.what() << endl;
return -1;
}
//...
return 0;
}
Exceptions in C++ resemble ones in languages such as C# and Java. In the try block, if an exception is thrown
it will be caught by the first associated catch block whose type matches that of the exception. In other words,
execution jumps from the throw statement to the catch statement. If no usable catch block is found,
std::terminate is invoked and the program exits. In C++, any type may be thrown; however, we recommend
that you throw a type that derives directly or indirectly from std::exception . In the previous example, the
exception type, invalid_argument , is defined in the standard library in the <stdexcept> header file. C++ doesn't
provide or require a finally block to make sure all resources are released if an exception is thrown. The
resource acquisition is initialization (RAII) idiom, which uses smart pointers, provides the required functionality
for resource cleanup. For more information, see How to: Design for exception safety. For information about the
C++ stack-unwinding mechanism, see Exceptions and stack unwinding.
Basic guidelines
Robust error handling is challenging in any programming language. Although exceptions provide several
features that support good error handling, they can't do all the work for you. To realize the benefits of the
exception mechanism, keep exceptions in mind as you design your code.
Use asserts to check for errors that should never occur. Use exceptions to check for errors that might
occur, for example, errors in input validation on parameters of public functions. For more information, see
the Exceptions versus assertions section.
Use exceptions when the code that handles the error is separated from the code that detects the error by
one or more intervening function calls. Consider whether to use error codes instead in performance-
critical loops, when code that handles the error is tightly coupled to the code that detects it.
For every function that might throw or propagate an exception, provide one of the three exception
guarantees: the strong guarantee, the basic guarantee, or the nothrow (noexcept) guarantee. For more
information, see How to: Design for exception safety.
Throw exceptions by value, catch them by reference. Don’t catch what you can't handle.
Don't use exception specifications, which are deprecated in C++11. For more information, see the
Exception specifications and noexcept section.
Use standard library exception types when they apply. Derive custom exception types from the
exception Class hierarchy.
See also
How to: Interface between exceptional and non-exceptional code
C++ language reference
C++ Standard Library
How to: Design for exception safety
3/6/2021 • 6 minutes to read • Edit Online
One of the advantages of the exception mechanism is that execution, together with data about the exception,
jumps directly from the statement that throws the exception to the first catch statement that handles it. The
handler may be any number of levels up in the call stack. Functions that are called between the try statement
and the throw statement are not required to know anything about the exception that is thrown. However, they
have to be designed so that they can go out of scope "unexpectedly" at any point where an exception might
propagate up from below, and do so without leaving behind partially created objects, leaked memory, or data
structures that are in unusable states.
Basic techniques
A robust exception-handling policy requires careful thought and should be part of the design process. In
general, most exceptions are detected and thrown at the lower layers of a software module, but typically these
layers do not have enough context to handle the error or expose a message to end users. In the middle layers,
functions can catch and rethrow an exception when they have to inspect the exception object, or they have
additional useful information to provide for the upper layer that ultimately catches the exception. A function
should catch and "swallow" an exception only if it is able to completely recover from it. In many cases, the
correct behavior in the middle layers is to let an exception propagate up the call stack. Even at the highest layer,
it might be appropriate to let an unhandled exception terminate a program if the exception leaves the program
in a state in which its correctness cannot be guaranteed.
No matter how a function handles an exception, to help guarantee that it is "exception-safe," it must be designed
according to the following basic rules.
Keep resource classes simple
When you encapsulate manual resource management in classes, use a class that does nothing except manage a
single resource. By keeping the class simple, you reduce the risk of introducing resource leaks. Use smart
pointers when possible, as shown in the following example. This example is intentionally artificial and simplistic
to highlight the differences when shared_ptr is used.
// old-style new/delete version
class NDResourceClass {
private:
int* m_p;
float* m_q;
public:
NDResourceClass() : m_p(0), m_q(0) {
m_p = new int;
m_q = new float;
}
~NDResourceClass() {
delete m_p;
delete m_q;
}
// Potential leak! When a constructor emits an exception,
// the destructor will not be invoked.
};
// shared_ptr version
#include <memory>
class SPResourceClass {
private:
shared_ptr<int> m_p;
shared_ptr<float> m_q;
public:
SPResourceClass() : m_p(new int), m_q(new float) { }
// Implicitly defined dtor is OK for these members,
// shared_ptr will clean up and avoid leaks regardless.
};
class Shape {
// ...
};
class SPShapeResourceClass {
private:
shared_ptr<Shape> m_p;
shared_ptr<Shape> m_q;
public:
SPShapeResourceClass() : m_p(new Circle), m_q(new Triangle) { }
};
Exception-safe classes
A class can help ensure its own exception safety, even when it is consumed by unsafe functions, by preventing
itself from being partially constructed or partially destroyed. If a class constructor exits before completion, then
the object is never created and its destructor will never be called. Although automatic variables that are
initialized prior to the exception will have their destructors invoked, dynamically allocated memory or resources
that are not managed by a smart pointer or similar automatic variable will be leaked.
The built-in types are all no-fail, and the Standard Library types support the basic guarantee at a minimum.
Follow these guidelines for any user-defined type that must be exception-safe:
Use smart pointers or other RAII-type wrappers to manage all resources. Avoid resource management
functionality in your class destructor, because the destructor will not be invoked if the constructor throws
an exception. However, if the class is a dedicated resource manager that controls just one resource, then
it's acceptable to use the destructor to manage resources.
Understand that an exception thrown in a base class constructor cannot be swallowed in a derived class
constructor. If you want to translate and re-throw the base class exception in a derived constructor, use a
function try block.
Consider whether to store all class state in a data member that is wrapped in a smart pointer, especially if
a class has a concept of "initialization that is permitted to fail." Although C++ allows for uninitialized data
members, it does not support uninitialized or partially initialized class instances. A constructor must
either succeed or fail; no object is created if the constructor does not run to completion.
Do not allow any exceptions to escape from a destructor. A basic axiom of C++ is that destructors should
never allow an exception to propagate up the call stack. If a destructor must perform a potentially
exception-throwing operation, it must do so in a try catch block and swallow the exception. The standard
library provides this guarantee on all destructors it defines.
See also
Modern C++ best practices for exceptions and error handling
How to: Interface Between Exceptional and Non-Exceptional Code
How to: Interface between exceptional and non-
exceptional code
3/6/2021 • 6 minutes to read • Edit Online
This article describes how to implement consistent exception-handling in a C++ module, and also how to
translate those exceptions to and from error codes at the exception boundaries.
Sometimes a C++ module has to interface with code that doesn't use exceptions (non-exceptional code). Such
an interface is known as an exception boundary. For example, you may want to call the Win32 function
CreateFile in your C++ program. CreateFile doesn't throw exceptions; instead it sets error codes that can be
retrieved by the GetLastError function. If your C++ program is non-trivial, then in it you probably prefer to
have a consistent exception-based error-handling policy. And you probably don't want to abandon exceptions
just because you interface with non-exceptional code, and neither do you want to mix exception-based and non-
exception-based error policies in your C++ module.
class File
{
private:
HANDLE m_handle;
~File() { CloseHandle(m_handle); }
vector<char> readbuffer(filesize);
cout << filename << " file size: " << filesize << ", bytesRead: "
<< bytesRead << endl;
return readbuffer;
}
#include <iomanip>
try
{
if(argc > 2) {
filename1 = argv[1];
filename2 = argv[2];
}
cout << "Using file names " << filename1 << " and " << filename2 << endl;
if (IsFileDiff(filename1, filename2)) {
cout << "+++ Files are different." << endl;
} else {
cout<< "=== Files match." << endl;
}
}
catch(const Win32Exception& e)
{
ios state(nullptr);
state.copyfmt(cout);
cout << e.what() << endl;
cout << "Error code: 0x" << hex << uppercase << setw(8) << setfill('0')
<< e.GetErrorCode() << endl;
cout.copyfmt(state); // restore previous formatting
}
}
catch(std::exception& e)
{
SetLastError(MY_APPLICATION_GENERAL_ERROR);
}
return FALSE;
}
When you convert from exceptions to error codes, one potential issue is that error codes often don't contain the
richness of information that an exception can store. To address this, you can provide a catch block for each
specific exception type that might be thrown, and perform logging to record the details of the exception before it
is converted to an error code. This approach can create a lot of code repetition if multiple functions all use the
same set of catch blocks. A good way to avoid code repetition is by refactoring those blocks into one private
utility function that implements the try and catch blocks and accepts a function object that is invoked in the
try block. In each public function, pass the code to the utility function as a lambda expression.
template<typename Func>
bool Win32ExceptionBoundary(Func&& f)
{
try
{
return f();
}
catch(Win32Exception& e)
{
SetLastError(e.GetErrorCode());
}
catch(const std::exception& e)
{
SetLastError(MY_APPLICATION_GENERAL_ERROR);
}
return false;
}
The following example shows how to write the lambda expression that defines the functor. When a functor is
defined "inline" by using a lambda expression, it is often easier to read than it would be if it were written as a
named function object.
bool DiffFiles3(const string& file1, const string& file2)
{
return Win32ExceptionBoundary([&]() -> bool
{
File f1(file1);
File f2(file2);
if (IsTextFileDiff(f1, f2))
{
SetLastError(MY_APPLICATION_ERROR_FILE_MISMATCH);
return false;
}
return true;
});
}
See also
Modern C++ best practices for exceptions and error handling
How to: Design for Exception Safety
try, throw, and catch Statements (C++)
3/6/2021 • 2 minutes to read • Edit Online
To implement exception handling in C++, you use try , throw , and catch expressions.
First, use a try block to enclose one or more statements that might throw an exception.
A throw expression signals that an exceptional condition—often, an error—has occurred in a try block. You
can use an object of any type as the operand of a throw expression. Typically, this object is used to
communicate information about the error. In most cases, we recommend that you use the std::exception class or
one of the derived classes that are defined in the standard library. If one of those is not appropriate, we
recommend that you derive your own exception class from std::exception .
To handle exceptions that may be thrown, implement one or more catch blocks immediately following a try
block. Each catch block specifies the type of exception it can handle.
This example shows a try block and its handlers. Assume that GetNetworkResource() acquires data over a
network connection and that the two exception types are user-defined classes that derive from std::exception .
Notice that the exceptions are caught by const reference in the catch statement. We recommend that you
throw exceptions by value and catch them by const reference.
Example
MyData md;
try {
// Code that could throw an exception
md = GetNetworkResource();
}
catch (const networkIOException& e) {
// Code that executes when an exception of type
// networkIOException is thrown in the try block
// ...
// Log error message in the exception object
cerr << e.what();
}
catch (const myDataFormatException& e) {
// Code that handles another exception type
// ...
cerr << e.what();
}
Remarks
The code after the try clause is the guarded section of code. The throw expression throws—that is, raises—an
exception. The code block after the catch clause is the exception handler. This is the handler that catches the
exception that's thrown if the types in the throw and catch expressions are compatible. For a list of rules that
govern type-matching in catch blocks, see How Catch Blocks are Evaluated. If the catch statement specifies an
ellipsis (...) instead of a type, the catch block handles every type of exception. When you compile with the /EHa
option, these can include C structured exceptions and system-generated or application-generated asynchronous
exceptions such as memory protection, divide-by-zero, and floating-point violations. Because catch blocks are
processed in program order to find a matching type, an ellipsis handler must be the last handler for the
associated try block. Use catch(...) with caution; do not allow a program to continue unless the catch block
knows how to handle the specific exception that is caught. Typically, a catch(...) block is used to log errors and
perform special cleanup before program execution is stopped.
A throw expression that has no operand re-throws the exception currently being handled. We recommend this
form when re-throwing the exception, because this preserves the original exception’s polymorphic type
information. Such an expression should only be used in a catch handler or in a function that's called from a
catch handler. The re-thrown exception object is the original exception object, not a copy.
try {
throw CSomeOtherException();
}
catch(...) {
// Catch all exceptions - dangerous!!!
// Respond (perhaps only partially) to the exception, then
// re-throw to pass the exception to some other handler
// ...
throw;
}
See also
Modern C++ best practices for exceptions and error handling
Keywords
Unhandled C++ Exceptions
__uncaught_exception
How Catch Blocks are Evaluated (C++)
3/6/2021 • 2 minutes to read • Edit Online
C++ enables you to throw exceptions of any type, although in general it is recommended to throw types that
are derived from std::exception. A C++ exception can be caught by a catch handler that specifies the same type
as the thrown exception, or by a handler that can catch any type of exception.
If the type of thrown exception is a class, which also has a base class (or classes), it can be caught by handlers
that accept base classes of the exception's type, as well as references to bases of the exception's type. Note that
when an exception is caught by a reference, it is bound to the actual thrown exception object; otherwise, it is a
copy (much the same as an argument to a function).
When an exception is thrown, it may be caught by the following types of catch handlers:
A handler that can accept any type (using the ellipsis syntax).
A handler that accepts the same type as the exception object; because it is a copy, const and volatile
modifiers are ignored.
A handler that accepts a reference to the same type as the exception object.
A handler that accepts a reference to a const or volatile form of the same type as the exception object.
A handler that accepts a base class of the same type as the exception object; since it is a copy, const and
volatile modifiers are ignored. The catch handler for a base class must not precede the catch
handler for the derived class.
A handler that accepts a reference to a base class of the same type as the exception object.
A handler that accepts a reference to a const or volatile form of a base class of the same type as the
exception object.
A handler that accepts a pointer to which a thrown pointer object can be converted via standard pointer
conversion rules.
The order in which catch handlers appear is significant, because handlers for a given try block are examined
in order of their appearance. For example, it is an error to place the handler for a base class before the handler
for a derived class. After a matching catch handler is found, subsequent handlers are not examined. As a result,
an ellipsis catch handler must be the last handler for its try block. For example:
// ...
try
{
// ...
}
catch( ... )
{
// Handle exception here.
}
// Error: the next two handlers are never examined.
catch( const char * str )
{
cout << "Caught exception: " << str << endl;
}
catch( CExcptClass E )
{
// Handle CExcptClass exception here.
}
In this example, the ellipsis catch handler is the only handler that is examined.
See also
Modern C++ best practices for exceptions and error handling
Exceptions and Stack Unwinding in C++
3/6/2021 • 4 minutes to read • Edit Online
In the C++ exception mechanism, control moves from the throw statement to the first catch statement that can
handle the thrown type. When the catch statement is reached, all of the automatic variables that are in scope
between the throw and catch statements are destroyed in a process that is known as stack unwinding. In stack
unwinding, execution proceeds as follows:
1. Control reaches the try statement by normal sequential execution. The guarded section in the try
block is executed.
2. If no exception is thrown during execution of the guarded section, the catch clauses that follow the try
block are not executed. Execution continues at the statement after the last catch clause that follows the
associated try block.
3. If an exception is thrown during execution of the guarded section or in any routine that the guarded
section calls either directly or indirectly, an exception object is created from the object that is created by
the throw operand. (This implies that a copy constructor may be involved.) At this point, the compiler
looks for a catch clause in a higher execution context that can handle an exception of the type that is
thrown, or for a catch handler that can handle any type of exception. The catch handlers are examined
in order of their appearance after the try block. If no appropriate handler is found, the next dynamically
enclosing try block is examined. This process continues until the outermost enclosing try block is
examined.
4. If a matching handler is still not found, or if an exception occurs during the unwinding process but before
the handler gets control, the predefined run-time function terminate is called. If an exception occurs
after the exception is thrown but before the unwind begins, terminate is called.
5. If a matching catch handler is found, and it catches by value, its formal parameter is initialized by
copying the exception object. If it catches by reference, the parameter is initialized to refer to the
exception object. After the formal parameter is initialized, the process of unwinding the stack begins. This
involves the destruction of all automatic objects that were fully constructed—but not yet destructed—
between the beginning of the try block that is associated with the catch handler and the throw site of
the exception. Destruction occurs in reverse order of construction. The catch handler is executed and the
program resumes execution after the last handler—that is, at the first statement or construct that is not a
catch handler. Control can only enter a catch handler through a thrown exception, never through a
goto statement or a case label in a switch statement.
class MyException{};
class Dummy
{
public:
Dummy(string s) : MyName(s) { PrintMsg("Created Dummy:"); }
Dummy(const Dummy& other) : MyName(other.MyName){ PrintMsg("Copy created Dummy:"); }
~Dummy(){ PrintMsg("Destroyed Dummy:"); }
void PrintMsg(string s) { cout << s << MyName << endl; }
string MyName;
int level;
};
int main()
{
cout << "Entering main" << endl;
try
{
Dummy d(" M");
A(d,1);
}
catch (MyException& e)
{
cout << "Caught an exception of type: " << typeid(e).name() << endl;
}
/* Output:
Entering main
Created Dummy: M
Copy created Dummy: M
Entering FunctionA
Copy created Dummy: A
Entering FunctionB
Copy created Dummy: B
Copy created Dummy: B
Entering FunctionC
Destroyed Dummy: C
Destroyed Dummy: B
Destroyed Dummy: A
Destroyed Dummy: M
Caught an exception of type: class MyException
Exiting main.
*/
Exception specifications (throw, noexcept) (C++)
3/6/2021 • 3 minutes to read • Edit Online
Exception specifications are a C++ language feature that indicate the programmer's intent about the exception
types that can be propagated by a function. You can specify that a function may or may not exit by an exception
by using an exception specification. The compiler can use this information to optimize calls to the function, and
to terminate the program if an unexpected exception escapes the function.
Prior to C++17 there were two kinds of exception specification. The noexcept specification was new in C++11. It
specifies whether the set of potential exceptions that can escape the function is empty. The dynamic exception
specification, or throw(optional_type_list) specification, was deprecated in C++11 and removed in C++17,
except for throw() , which is an alias for noexcept(true) . This exception specification was designed to provide
summary information about what exceptions can be thrown out of a function, but in practice it was found to be
problematic. The one dynamic exception specification that did prove to be somewhat useful was the
unconditional throw() specification. For example, the function declaration:
tells the compiler that the function does not throw any exceptions. However, in /std:c++14 mode this could
lead to undefined behavior if the function does throw an exception. Therefore we recommend using the
noexcept operator instead of the one above:
The following table summarizes the Microsoft C++ implementation of exception specifications:
EXC EP T IO N SP EC IF IC AT IO N M EA N IN G
If exception handling is used in an application, there must be a function in the call stack that handles thrown
exceptions before they exit the outer scope of a function marked noexcept , noexcept(true) , or throw() . If any
functions called between the one that throws an exception and the one that handles the exception are specified
as noexcept , noexcept(true) (or throw() in /std:c++17 mode), the program is terminated when the noexcept
function propagates the exception.
The exception behavior of a function depends on the following factors:
Which language standard compilation mode is set.
Whether you are compiling the function under C or C++.
Which /EH compiler option you use.
Whether you explicitly specify the exception specification.
Explicit exception specifications are not allowed on C functions. A C function is assumed not to throw exceptions
under /EHsc , and may throw structured exceptions under /EHs , /EHa , or /EHac .
The following table summarizes whether a C++ function may potentially throw under various compiler
exception handling options:
F UN C T IO N / EH SC / EH S / EH A / EH A C
Example
// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>
void handler() {
printf_s("in handler\n");
}
int main() {
f2();
try {
f4();
}
catch(...) {
printf_s("Caught exception from f4\n");
}
f5();
}
About to throw 1
in handler
About to throw 1
Caught exception from f4
About to throw 1
in handler
See also
try, throw, and catch Statements (C++)
Modern C++ best practices for exceptions and error handling
noexcept (C++)
3/6/2021 • 2 minutes to read • Edit Online
Syntax
noexcept-expression:
noexcept
noexcept( constant-expression )
Parameters
constant-expression
A constant expression of type bool that represents whether the set of potential exception types is empty. The
unconditional version is equivalent to noexcept(true) .
Remarks
A noexcept expression is a kind of exception specification, a suffix to a function declaration that represents a set
of types that might be matched by an exception handler for any exception that exits a function. Unary
conditional operator noexcept( constant_expression ) where constant_expression yields true , and its
unconditional synonym noexcept , specify that the set of potential exception types that can exit a function is
empty. That is, the function never throws an exception and never allows an exception to be propagated outside
its scope. The operator noexcept( constant_expression ) where constant_expression yields false , or the
absence of an exception specification (other than for a destructor or deallocation function), indicates that the set
of potential exceptions that can exit the function is the set of all types.
Mark a function as noexcept only if all the functions that it calls, either directly or indirectly, are also noexcept
or const . The compiler does not necessarily check every code path for exceptions that might bubble up to a
noexcept function. If an exception does exit the outer scope of a function marked noexcept , std::terminate is
invoked immediately, and there is no guarantee that destructors of any in-scope objects will be invoked. Use
noexcept instead of the dynamic exception specifier throw() , which is now deprecated in the standard. We
recommended you apply noexcept to any function that never allows an exception to propagate up the call
stack. When a function is declared noexcept , it enables the compiler to generate more efficient code in several
different contexts. For more information, see Exception specifications.
Example
A template function that copies its argument might be declared noexcept on the condition that the object being
copied is a plain old data type (POD). Such a function could be declared like this:
#include <type_traits>
If a matching handler (or ellipsis catch handler) cannot be found for the current exception, the predefined
terminate run-time function is called. (You can also explicitly call terminate in any of your handlers.) The
default action of terminate is to call abort . If you want terminate to call some other function in your program
before exiting the application, call the set_terminate function with the name of the function to be called as its
single argument. You can call set_terminate at any point in your program. The terminate routine always calls
the last function given as an argument to set_terminate .
Example
The following example throws a char * exception, but does not contain a handler designated to catch
exceptions of type char * . The call to set_terminate instructs terminate to call term_func .
// exceptions_Unhandled_Exceptions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void term_func() {
cout << "term_func was called by terminate." << endl;
exit( -1 );
}
int main() {
try
{
set_terminate( term_func );
throw "Out of memory!"; // No catch handler for this exception
}
catch( int )
{
cout << "Integer exception raised." << endl;
}
return 0;
}
Output
term_func was called by terminate.
The term_func function should terminate the program or current thread, ideally by calling exit . If it doesn't,
and instead returns to its caller, abort is called.
See also
Modern C++ best practices for exceptions and error handling
Mixing C (structured) and C++ exceptions
11/2/2020 • 2 minutes to read • Edit Online
If you want to write portable code, the use of structured exception handling (SEH) in a C++ program isn't
recommended. However, you may sometimes want to compile using /EHa and mix structured exceptions and
C++ source code, and need some facility for handling both kinds of exceptions. Because a structured exception
handler has no concept of objects or typed exceptions, it can't handle exceptions thrown by C++ code. However,
C++ catch handlers can handle structured exceptions. C++ exception handling syntax ( try , throw , catch )
isn't accepted by the C compiler, but structured exception handling syntax ( __try , __except , __finally ) is
supported by the C++ compiler.
See _set_se_translator for information on how to handle structured exceptions as C++ exceptions.
If you mix structured and C++ exceptions, be aware of these potential issues:
C++ exceptions and structured exceptions can't be mixed within the same function.
Termination handlers ( __finally blocks) are always executed, even during unwinding after an exception
is thrown.
C++ exception handling can catch and preserve the unwind semantics in all modules compiled with the
/EH compiler options, which enable unwind semantics.
There may be some situations in which destructor functions aren't called for all objects. For example, a
structured exception could occur while attempting to make a function call through an uninitialized
function pointer. If the function parameters are objects constructed before the call, the destructors of
those objects don't get called during stack unwind.
Next steps
Using setjmp or longjmp in C++ programs
See more information on the use of setjmp and longjmp in C++ programs.
Handle structured exceptions in C++
See examples of the ways you can use C++ to handle structured exceptions.
See also
Modern C++ best practices for exceptions and error handling
Using setjmp and longjmp
3/6/2021 • 2 minutes to read • Edit Online
When setjmp and longjmp are used together, they provide a way to execute a non-local goto . They are typically
used in C code to pass execution control to error-handling or recovery code in a previously called routine
without using the standard calling or return conventions.
Cau t i on
Because setjmp and longjmp don't support correct destruction of stack frame objects portably between C++
compilers, and because they might degrade performance by preventing optimization on local variables, we don't
recommend their use in C++ programs. We recommend you use try and catch constructs instead.
If you decide to use setjmp and longjmp in a C++ program, also include <setjmp.h> or <setjmpex.h> to
assure correct interaction between the functions and Structured Exception Handling (SEH) or C++ exception
handling.
Microsoft Specific
If you use an /EH option to compile C++ code, destructors for local objects are called during the stack unwind.
However, if you use /EHs or /EHsc to compile, and one of your functions that uses noexcept calls longjmp , then
the destructor unwind for that function might not occur, depending on the optimizer state.
In portable code, when a longjmp call is executed, correct destruction of frame-based objects is explicitly not
guaranteed by the standard, and may not be supported by other compilers. To let you know, at warning level 4, a
call to setjmp causes warning C4611: interaction between '_setjmp' and C++ object destruction is non-
portable.
END Microsoft Specific
See also
Mixing C (Structured) and C++ Exceptions
Handle structured exceptions in C++
11/2/2020 • 4 minutes to read • Edit Online
The major difference between C structured exception handling (SEH) and C++ exception handling is that the
C++ exception handling model deals in types, while the C structured exception handling model deals with
exceptions of one type; specifically, unsigned int . That is, C exceptions are identified by an unsigned integer
value, whereas C++ exceptions are identified by data type. When a structured exception is raised in C, each
possible handler executes a filter that examines the C exception context and determines whether to accept the
exception, pass it to some other handler, or ignore it. When an exception is thrown in C++, it may be of any type.
A second difference is that the C structured exception handling model is referred to as asynchronous, because
exceptions occur secondary to the normal flow of control. The C++ exception handling mechanism is fully
synchronous, which means that exceptions occur only when they are thrown.
When you use the /EHs or /EHsc compiler option, no C++ exception handlers handle structured exceptions.
These exceptions are handled only by __except structured exception handlers or __finally structured
termination handlers. For information, see Structured Exception Handling (C/C++).
Under the /EHa compiler option, if a C exception is raised in a C++ program, it can be handled by a structured
exception handler with its associated filter or by a C++ catch handler, whichever is dynamically nearer to the
exception context. For example, this sample C++ program raises a C exception inside a C++ try context:
int main() {
try {
SEHFunc();
}
catch( ... ) {
cout << "Caught a C exception."<< endl;
}
}
void SEHFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
cout << "In finally." << endl;
}
}
In finally.
Caught a C exception.
C exception wrapper classes
In a simple example like the above, the C exception can be caught only by an ellipsis (...) catch handler. No
information about the type or nature of the exception is communicated to the handler. While this method works,
in some cases you may want to define a transformation between the two exception handling models so that
each C exception is associated with a specific class. To transform one, you can define a C exception "wrapper"
class, which can be used or derived from in order to attribute a specific class type to a C exception. By doing so,
each C exception can be handled separately by a specific C++ catch handler, instead of all of them in a single
handler.
Your wrapper class might have an interface consisting of some member functions that determine the value of
the exception, and that access the extended exception context information provided by the C exception model.
You might also want to define a default constructor and a constructor that accepts an unsigned int argument
(to provide for the underlying C exception representation), and a bitwise copy constructor. Here is a possible
implementation of a C exception wrapper class:
// exceptions_Exception_Handling_Differences2.cpp
// compile with: /c
class SE_Exception {
private:
SE_Exception() {}
SE_Exception( SE_Exception& ) {}
unsigned int nSE;
public:
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() {
return nSE;
}
};
To use this class, install a custom C exception translation function that is called by the internal exception
handling mechanism each time a C exception is thrown. Within your translation function, you can throw any
typed exception (perhaps an SE_Exception type, or a class type derived from SE_Exception ) that can be caught
by an appropriate matching C++ catch handler. The translation function can instead return, which indicates
that it did not handle the exception. If the translation function itself raises a C exception, terminate is called.
To specify a custom translation function, call the _set_se_translator function with the name of your translation
function as its single argument. The translation function that you write is called once for each function
invocation on the stack that has try blocks. There is no default translation function; if you do not specify one by
calling _set_se_translator , the C exception can only be caught by an ellipsis catch handler.
class SE_Exception {
private:
SE_Exception() {}
unsigned int nSE;
public:
SE_Exception( SE_Exception& e) : nSE(e.nSE) {}
SE_Exception(unsigned int n) : nSE(n) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
void SEFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
printf_s( "In finally\n" );
}
}
int main() {
_set_se_translator( trans_func );
try {
SEFunc();
}
catch( SE_Exception e ) {
printf_s( "Caught a __try exception with SE_Exception.\n" );
printf_s( "nSE = 0x%x\n", e.getSeNumber() );
}
}
In trans_func.
In finally
Caught a __try exception with SE_Exception.
nSE = 0xc0000094
See also
Mixing C (Structured) and C++ exceptions
Structured Exception Handling (C/C++)
11/2/2020 • 4 minutes to read • Edit Online
Structured exception handling (SEH) is a Microsoft extension to C to handle certain exceptional code situations,
such as hardware faults, gracefully. Although Windows and Microsoft C++ support SEH, we recommend that
you use ISO-standard C++ exception handling. It makes your code more portable and flexible. However, to
maintain existing code or for particular kinds of programs, you still might have to use SEH.
Microsoft-specific:
Grammar
try-except-statement :
__try compound-statement __except ( expression ) compound-statement
try-finally-statement :
__try compound-statement __finally compound-statement
Remarks
With SEH, you can ensure that resources, such as memory blocks and files, get released correctly if execution
unexpectedly terminates. You can also handle specific problems—for example, insufficient memory—by using
concise structured code that doesn't rely on goto statements or elaborate testing of return codes.
The try-except and try-finally statements referred to in this article are Microsoft extensions to the C
language. They support SEH by enabling applications to gain control of a program after events that would
otherwise terminate execution. Although SEH works with C++ source files, it's not specifically designed for C++.
If you use SEH in a C++ program that you compile by using the /EHa or /EHsc option, destructors for local
objects are called but other execution behavior might not be what you expect. For an illustration, see the
example later in this article. In most cases, instead of SEH we recommend that you use ISO-standard C++
exception handling, which the Microsoft C++ compiler also supports. By using C++ exception handling, you can
ensure that your code is more portable, and you can handle exceptions of any type.
If you have C code that uses SEH, you can mix it with C++ code that uses C++ exception handling. For
information, see Handle structured exceptions in C++.
There are two SEH mechanisms:
Exception handlers, or __except blocks, which can respond to or dismiss the exception.
Termination handlers, or __finally blocks, which are always called, whether an exception causes
termination or not.
These two kinds of handlers are distinct, but are closely related through a process known as unwinding the
stack. When a structured exception occurs, Windows looks for the most recently installed exception handler
that's currently active. The handler can do one of three things:
Fail to recognize the exception and pass control to other handlers.
Recognize the exception but dismiss it.
Recognize the exception and handle it.
The exception handler that recognizes the exception may not be in the function that was running when the
exception occurred. It may be in a function much higher on the stack. The currently running function and all
other functions on the stack frame are terminated. During this process, the stack is unwound. That is, local non-
static variables of terminated functions get cleared from the stack.
As it unwinds the stack, the operating system calls any termination handlers that you've written for each
function. By using a termination handler, you clean up resources that otherwise would remain open because of
an abnormal termination. If you've entered a critical section, you can exit it in the termination handler. When the
program is going to shut down, you can do other housekeeping tasks such as closing and removing temporary
files.
Next steps
Writing an exception handler
Writing a termination handler
Handle structured exceptions in C++
Example
As stated earlier, destructors for local objects are called if you use SEH in a C++ program and compile it by using
the /EHa or /EHsc option. However, the behavior during execution may not be what you expect if you're also
using C++ exceptions. This example demonstrates these behavioral differences.
#include <stdio.h>
#include <Windows.h>
#include <exception>
class TestClass
{
public:
~TestClass()
{
printf("Destroying TestClass!\r\n");
}
};
int main()
{
__try
{
TestExceptions();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("Executing SEH __except block\r\n");
}
return 0;
}
If you use /EHsc to compile this code but the local test control macro CPPEX is undefined, the TestClass
destructor doesn't run. The output looks like this:
If you use /EHsc to compile the code and CPPEX is defined by using /DCPPEX (so that a C++ exception is
thrown), the TestClass destructor runs, and the output looks like this:
If you use /EHa to compile the code, the TestClass destructor executes whether the exception was thrown by
using std::throw or by using SEH to trigger the exception. That is, whether CPPEX is defined or not. The output
looks like this:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
See also
Exception handling
Keywords
<exception>
Errors and exception handling
Structured Exception Handling (Windows)
Writing an Exception Handler
3/6/2021 • 2 minutes to read • Edit Online
Exception handlers are typically used to respond to specific errors. You can use the exception-handling syntax to
filter out all exceptions other than those you know how to handle. Other exceptions should be passed to other
handlers (possibly in the run-time library or the operating system) written to look for those specific exceptions.
Exception handlers use the try-except statement.
See also
Structured Exception Handling (C/C++)
try-except statement
11/2/2020 • 4 minutes to read • Edit Online
The try-except statement is a Microsoft-specific extension that supports structured exception handling in the
C and C++ languages.
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
Grammar
try-except-statement :
__try compound-statement __except ( expression ) compound-statement
Remarks
The try-except statement is a Microsoft extension to the C and C++ languages. It enables target applications to
gain control when events occur that normally terminate program execution. Such events are called structured
exceptions, or exceptions for short. The mechanism that deals with these exceptions is called structured
exception handling (SEH).
For related information, see the try-finally statement.
Exceptions may be either hardware-based or software-based. Structured exception handling is useful even when
applications can't completely recover from hardware or software exceptions. SEH makes it possible to display
error information and trap the internal state of the application to help diagnose the problem. It's especially
useful for intermittent problems that aren't easy to reproduce.
NOTE
Structured exception handling works with Win32 for both C and C++ source files. However, it's not specifically designed
for C++. You can ensure that your code is more portable by using C++ exception handling. Also, C++ exception handling
is more flexible, in that it can handle exceptions of any type. For C++ programs, we recommend you use native C++
exception-handling: try, catch, and throw statements.
The compound statement after the __try clause is the body or guarded section. The __except expression is
also known as the filter expression. Its value determines how the exception is handled. The compound statement
after the __except clause is the exception handler. The handler specifies the actions to take if an exception is
raised during execution of the body section. Execution proceeds as follows:
1. The guarded section is executed.
2. If no exception occurs during execution of the guarded section, execution continues at the statement after
the __except clause.
3. If an exception occurs during execution of the guarded section, or in any routine the guarded section calls,
the __except expression is evaluated. There are three possible values:
EXCEPTION_CONTINUE_EXECUTION (-1) Exception is dismissed. Continue execution at the point where
the exception occurred.
EXCEPTION_CONTINUE_SEARCH (0) Exception isn't recognized. Continue to search up the stack for a
handler, first for containing try-except statements, then for handlers with the next highest
precedence.
EXCEPTION_EXECUTE_HANDLER (1) Exception is recognized. Transfer control to the exception handler
by executing the __except compound statement, then continue execution after the __except
block.
The __except expression is evaluated as a C expression. It's limited to a single value, the conditional-expression
operator, or the comma operator. If more extensive processing is required, the expression can call a routine that
returns one of the three values listed above.
Each application can have its own exception handler.
It's not valid to jump into a __try statement, but valid to jump out of one. The exception handler isn't called if a
process is terminated in the middle of executing a try-except statement.
For compatibility with previous versions, _tr y , _except , and _leave are synonyms for __try , __except , and
__leave unless compiler option /Za (Disable language extensions) is specified.
The pointer types PEXCEPTION_RECORD and PCONTEXT are defined in the include file <winnt.h>, and
_EXCEPTION_RECORD and _CONTEXT are defined in the include file <excpt.h>
You can use GetExceptionCode within the exception handler. However, you can use GetExceptionInformation only
within the exception filter expression. The information it points to is generally on the stack and is no longer
available when control gets transferred to the exception handler.
The intrinsic function AbnormalTermination is available within a termination handler. It returns 0 if the body of
the tr y-finally statement terminates sequentially. In all other cases, it returns 1.
<excpt.h> defines some alternate names for these intrinsics:
GetExceptionCode is equivalent to _exception_code
Example
// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
int main()
{
int* p = 0x00000000; // pointer to NULL
puts("hello");
__try
{
puts("in try");
__try
{
puts("in try");
*p = 13; // causes an access violation exception;
}
__finally
{
puts("in finally. termination: ");
puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
}
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
puts("in except");
}
puts("world");
}
Output
hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
abnormal
in except
world
See also
Writing an exception handler
Structured Exception Handling (C/C++)
Keywords
Writing an exception filter
3/6/2021 • 2 minutes to read • Edit Online
You can handle an exception either by jumping to the level of the exception handler or by continuing execution.
Instead of using the exception handler code to handle the exception and falling through, you can use a filter
expression to clean up the problem. Then, by returning EXCEPTION_CONTINUE_EXECUTION (-1), you may resume
normal flow without clearing the stack.
NOTE
Some exceptions cannot be continued. If filter evaluates to -1 for such an exception, the system raises a new exception.
When you call RaiseException , you determine whether the exception will continue.
For example, the following code uses a function call in the filter expression: this function handles the problem
and then returns -1 to resume normal flow of control:
// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int main() {
int Eval_Exception( int );
__try {}
}
void ResetVars( int ) {}
int Eval_Exception ( int n_except ) {
if ( n_except != STATUS_INTEGER_OVERFLOW &&
n_except != STATUS_FLOAT_OVERFLOW ) // Pass on most exceptions
return EXCEPTION_CONTINUE_SEARCH;
It's a good idea to use a function call in the filter expression whenever filter needs to do anything complex.
Evaluating the expression causes execution of the function, in this case, Eval_Exception .
Note the use of GetExceptionCode to determine the exception. This function must be called inside the filter
expression of the __except statement. Eval_Exception can't call GetExceptionCode , but it must have the
exception code passed to it.
This handler passes control to another handler unless the exception is an integer or floating-point overflow. If it
is, the handler calls a function ( ResetVars is only an example, not an API function) to reset some global
variables. The __except statement block, which in this example is empty, can never be executed because
Eval_Exception never returns EXCEPTION_EXECUTE_HANDLER (1).
Using a function call is a good general-purpose technique for dealing with complex filter expressions. Two other
C language features that are useful are:
The conditional operator
The comma operator
The conditional operator is frequently useful here. It can be used to check for a specific return code and then
return one of two different values. For example, the filter in the following code recognizes the exception only if
the exception is STATUS_INTEGER_OVERFLOW :
The purpose of the conditional operator in this case is mainly to provide clarity, because the following code
produces the same results:
The conditional operator is more useful in situations where you might want the filter to evaluate to -1,
EXCEPTION_CONTINUE_EXECUTION .
The comma operator lets you execute multiple expressions in sequence. It then returns the value of the last
expression. For example, the following code stores the exception code in a variable and then tests it:
See also
Writing an exception handler
Structured Exception Handling (C/C++)
Raising software exceptions
3/6/2021 • 2 minutes to read • Edit Online
Some of the most common sources of program errors are not flagged as exceptions by the system. For example,
if you attempt to allocate a memory block but there is insufficient memory, the run-time or API function does
not raise an exception but returns an error code.
However, you can treat any condition as an exception by detecting that condition in your code and then
reporting it by calling the RaiseException function. By flagging errors this way, you can bring the advantages of
structured exception handling to any kind of run-time error.
To use structured exception handling with errors:
Define your own exception code for the event.
Call RaiseException when you detect a problem.
Use exception-handling filters to test for the exception code you defined.
The <winerror.h> file shows the format for exception codes. To make sure that you do not define a code that
conflicts with an existing exception code, set the third most significant bit to 1. The four most-significant bits
should be set as shown in the following table.
You can set the first two bits to a setting other than 11 binary if you want, although the "error" setting is
appropriate for most exceptions. The important thing to remember is to set bits 29 and 28 as shown in the
previous table.
The resulting error code should therefore have the highest four bits set to hexadecimal E. For example, the
following definitions define exception codes that do not conflict with any Windows exception codes. (You may,
however, need to check which codes are used by third-party DLLs.)
After you have defined an exception code, you can use it to raise an exception. For example, the following code
raises the STATUS_INSUFFICIENT_MEM exception in response to a memory allocation problem:
__try {
...
}
__except (GetExceptionCode() == STATUS_INSUFFICIENT_MEM ||
GetExceptionCode() == STATUS_FILE_BAD_FORMAT )
See also
Writing an exception handler
Structured exception handling (C/C++)
Hardware exceptions
3/6/2021 • 2 minutes to read • Edit Online
Most of the standard exceptions recognized by the operating system are hardware-defined exceptions. Windows
recognizes a few low-level software exceptions, but these are usually best handled by the operating system.
Windows maps the hardware errors of different processors to the exception codes in this section. In some cases,
a processor may generate only a subset of these exceptions. Windows preprocesses information about the
exception and issues the appropriate exception code.
The hardware exceptions recognized by Windows are summarized in the following table:
Many of the exceptions listed in the previous table are intended to be handled by debuggers, the operating
system, or other low-level code. With the exception of integer and floating-point errors, your code should not
handle these errors. Thus, you should usually use the exception-handling filter to ignore exceptions (evaluate to
0). Otherwise, you may prevent lower-level mechanisms from responding appropriately. You can, however, take
appropriate precautions against the potential effect of these low-level errors by writing termination handlers.
See also
Writing an exception handler
Structured Exception Handling (C/C++)
Restrictions on exception handlers
11/2/2020 • 2 minutes to read • Edit Online
The principal limitation to using exception handlers in code is that you can't use a goto statement to jump into
a __try statement block. Instead, you must enter the statement block through normal flow of control. You can
jump out of a __try statement block, and you can nest exception handlers as you choose.
See also
Writing an exception handler
Structured Exception Handling (C/C++)
Writing a Termination Handler
3/6/2021 • 2 minutes to read • Edit Online
Unlike an exception handler, a termination handler is always executed, regardless of whether the protected block
of code terminated normally. The sole purpose of the termination handler should be to ensure that resources,
such as memory, handles, and files, are properly closed regardless of how a section of code finishes executing.
Termination handlers use the try-finally statement.
See also
Structured Exception Handling (C/C++)
try-finally statement
11/2/2020 • 3 minutes to read • Edit Online
The try-finally statement is a Microsoft-specific extension that supports structured exception handling in
the C and C++ languages.
Syntax
The following syntax describes the try-finally statement:
// . . .
__try {
// guarded code
}
__finally {
// termination code
}
// . . .
Grammar
try-finally-statement :
__try compound-statement __finally compound-statement
The try-finally statement is a Microsoft extension to the C and C++ languages that enable target applications
to guarantee execution of cleanup code when execution of a block of code is interrupted. Cleanup consists of
such tasks as deallocating memory, closing files, and releasing file handles. The try-finally statement is
especially useful for routines that have several places where a check is made for an error that could cause
premature return from the routine.
For related information and a code sample, see try-except Statement. For more information on structured
exception handling in general, see Structured Exception Handling. For more information on handling exceptions
in managed applications with C++/CLI, see Exception Handling under /clr .
NOTE
Structured exception handling works with Win32 for both C and C++ source files. However, it is not specifically designed
for C++. You can ensure that your code is more portable by using C++ exception handling. Also, C++ exception handling
is more flexible, in that it can handle exceptions of any type. For C++ programs, it is recommended that you use the C++
exception-handling mechanism ( try , catch , and throw statements).
The compound statement after the __try clause is the guarded section. The compound statement after the
__finally clause is the termination handler. The handler specifies a set of actions that execute when the
guarded section is exited, whether it exits the guarded section by an exception (abnormal termination), or by
standard fall through (normal termination).
Control reaches a __try statement by simple sequential execution (fall through). When control enters the
__try , its associated handler becomes active. If the flow of control reaches the end of the try block, execution
proceeds as follows:
1. The termination handler is invoked.
2. When the termination handler completes, execution continues after the __finally statement. However
the guarded section ends (for example, via a goto out of the guarded body or a return statement), the
termination handler is executed before the flow of control moves out of the guarded section.
A __finally statement doesn't block searching for an appropriate exception handler.
If an exception occurs in the __try block, the operating system must find a handler for the exception or the
program will fail. If a handler is found, any and all __finally blocks are executed and execution resumes in the
handler.
For example, suppose a series of function calls links function A to function D, as shown in the following figure.
Each function has one termination handler. If an exception is raised in function D and handled in A, the
termination handlers are called in this order as the system unwinds the stack: D, C, B.
NOTE
The behavior of try-finally is different from some other languages that support the use of finally , such as C#. A single
__try may have either, but not both, of __finally and __except . If both are to be used together, an outer try-
except statement must enclose the inner try-finally statement. The rules specifying when each block executes are also
different.
For compatibility with previous versions, _try , _finally , and _leave are synonyms for __try , __finally ,
and __leave unless compiler option /Za (Disable language extensions) is specified.
Abnormal Termination
Exiting a try-finally statement using the longjmp run-time function is considered abnormal termination. It
isn't legal to jump into a __try statement, but it's legal to jump out of one. All __finally statements that are
active between the point of departure (normal termination of the __try block) and the destination (the
__except block that handles the exception) must be run. It's called a local unwind.
If a __try block is prematurely terminated for any reason, including a jump out of the block, the system
executes the associated __finally block as a part of the process of unwinding the stack. In such cases, the
AbnormalTermination function returns true if called from within the __finally block; otherwise, it returns
false .
The termination handler isn't called if a process is killed in the middle of executing a try-finally statement.
END Microsoft-specific
See also
Writing a termination handler
Structured Exception Handling (C/C++)
Keywords
Termination-handler syntax
Cleaning up resources
11/2/2020 • 2 minutes to read • Edit Online
During termination-handler execution, you may not know which resources have been acquired before the
termination handler was called. It's possible that the __try statement block was interrupted before all resources
were acquired, so that not all resources were opened.
To be safe, you should check to see which resources are open before proceeding with termination-handling
cleanup. A recommended procedure is to:
1. Initialize handles to NULL.
2. In the __try statement block, acquire resources. Handles are set to positive values as the resource is
acquired.
3. In the __finally statement block, release each resource whose corresponding handle or flag variable is
nonzero or not NULL.
Example
For example, the following code uses a termination handler to close three files and release a memory block.
These resources were acquired in the __try statement block. Before cleaning up a resource, the code first
checks to see if the resource was acquired.
// exceptions_Cleaning_up_Resources.cpp
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <windows.h>
void fileOps() {
FILE *fp1 = NULL,
*fp2 = NULL,
*fp3 = NULL;
LPVOID lpvoid = NULL;
errno_t err;
__try {
lpvoid = malloc( BUFSIZ );
int main() {
fileOps();
}
See also
Writing a termination handler
Structured Exception Handling (C/C++)
Timing of exception handling: A summary
11/2/2020 • 2 minutes to read • Edit Online
A termination handler is executed no matter how the __try statement block is terminated. Causes include
jumping out of the __try block, a longjmp statement that transfers control out of the block, and unwinding the
stack due to exception handling.
NOTE
The Microsoft C++ compiler supports two forms of the setjmp and longjmp statements. The fast version bypasses
termination handling but is more efficient. To use this version, include the file <setjmp.h>. The other version supports
termination handling as described in the previous paragraph. To use this version, include the file <setjmpex.h>. The
increase in performance of the fast version depends on hardware configuration.
The operating system executes all termination handlers in the proper order before any other code can be
executed, including the body of an exception handler.
When the cause for interruption is an exception, the system must first execute the filter portion of one or more
exception handlers before deciding what to terminate. The order of events is:
1. An exception is raised.
2. The system looks at the hierarchy of active exception handlers and executes the filter of the handler with
highest precedence. That's the exception handler most recently installed and most deeply nested, going
by blocks and function calls.
3. If this filter passes control (returns 0), the process continues until a filter is found that doesn't pass
control.
4. If this filter returns -1, execution continues where the exception was raised, and no termination takes
place.
5. If the filter returns 1, the following events occur:
The system unwinds the stack: It clears all stack frames between where the exception was raised
and the stack frame that contains the exception handler.
As the stack is unwound, each termination handler on the stack is executed.
The exception handler itself is executed.
Control passes to the line of code after the end of this exception handler.
See also
Writing a termination handler
Structured Exception Handling (C/C++)
Restrictions on Termination Handlers
11/2/2020 • 2 minutes to read • Edit Online
You can't use a goto statement to jump into a __try statement block or a __finally statement block. Instead,
you must enter the statement block through normal flow of control. (You can, however, jump out of a __try
statement block.) Also, you can't nest an exception handler or termination handler inside a __finally block.
Some kinds of code permitted in a termination handler produce questionable results, so you should use them
with caution, if at all. One is a goto statement that jumps out of a __finally statement block. If the block
executes as part of normal termination, nothing unusual happens. But if the system is unwinding the stack, that
unwinding stops. Then, the current function gains control as if there were no abnormal termination.
A return statement inside a __finally statement block presents roughly the same situation. Control returns to
the immediate caller of the function that contains the termination handler. If the system was unwinding the
stack, this process is halted. Then, the program proceeds as if no exception had been raised.
See also
Writing a termination handler
Structured Exception Handling (C/C++)
Transporting exceptions between threads
3/6/2021 • 10 minutes to read • Edit Online
The Microsoft C++ compiler (MSVC) supports transporting an exception from one thread to another.
Transporting exceptions enables you to catch an exception in one thread and then make the exception appear to
be thrown in a different thread. For example, you can use this feature to write a multithreaded application where
the primary thread handles all the exceptions thrown by its secondary threads. Transporting exceptions is useful
mostly to developers who create parallel programming libraries or systems. To implement transporting
exceptions, MSVC provides the exception_ptr type and the current_exception, rethrow_exception, and
make_exception_ptr functions.
Syntax
namespace std
{
typedef unspecified exception_ptr;
exception_ptr current_exception();
void rethrow_exception(exception_ptr p);
template<class E>
exception_ptr make_exception_ptr(E e) noexcept;
}
Parameters
unspecified
An unspecified internal class that is used to implement the exception_ptr type.
p
An exception_ptr object that references an exception.
E
A class that represents an exception.
e
An instance of the parameter E class.
Return value
The current_exception function returns an exception_ptr object that references the exception that is currently
in progress. If no exception is in progress, the function returns an exception_ptr object that is not associated
with any exception.
The make_exception_ptr function returns an exception_ptr object that references the exception specified by the
e parameter.
Remarks
Scenario
Imagine that you want to create an application that can scale to handle a variable amount of work. To achieve
this objective, you design a multithreaded application where an initial, primary thread creates as many
secondary threads as it needs in order to do the job. The secondary threads help the primary thread to manage
resources, to balance loads, and to improve throughput. By distributing the work, the multithreaded application
performs better than a single-threaded application.
However, if a secondary thread throws an exception, you want the primary thread to handle it. This is because
you want your application to handle exceptions in a consistent, unified manner regardless of the number of
secondary threads.
Solution
To handle the previous scenario, the C++ Standard supports transporting an exception between threads. If a
secondary thread throws an exception, that exception becomes the current exception. By analogy to the real
world, the current exception is said to be in flight. The current exception is in flight from the time it is thrown
until the exception handler that catches it returns.
The secondary thread can catch the current exception in a catch block, and then call the current_exception
function to store the exception in an exception_ptr object. The exception_ptr object must be available to the
secondary thread and to the primary thread. For example, the exception_ptr object can be a global variable
whose access is controlled by a mutex. The term transport an exception means an exception in one thread can
be converted to a form that can be accessed by another thread.
Next, the primary thread calls the rethrow_exception function, which extracts and then throws the exception
from the exception_ptr object. When the exception is thrown, it becomes the current exception in the primary
thread. That is, the exception appears to originate in the primary thread.
Finally, the primary thread can catch the current exception in a catch block and then process it or throw it to a
higher level exception handler. Or, the primary thread can ignore the exception and allow the process to end.
Most applications do not have to transport exceptions between threads. However, this feature is useful in a
parallel computing system because the system can divide work among secondary threads, processors, or cores.
In a parallel computing environment, a single, dedicated thread can handle all the exceptions from the
secondary threads and can present a consistent exception-handling model to any application.
For more information about the C++ Standards committee proposal, search the Internet for document number
N2179, titled "Language Support for Transporting Exceptions between Threads".
Exception-handling models and compiler options
Your application's exception-handling model determines whether it can catch and transport an exception. Visual
C++ supports three models that can handle C++ exceptions, structured exception handling (SEH) exceptions,
and common language runtime (CLR) exceptions. Use the /EH and /clr compiler options to specify your
application's exception-handling model.
Only the following combination of compiler options and programming statements can transport an exception.
Other combinations either cannot catch exceptions, or can catch but cannot transport exceptions.
The /EHa compiler option and the catch statement can transport SEH and C++ exceptions.
The /EHa , /EHs , and /EHsc compiler options and the catch statement can transport C++ exceptions.
The /CLR compiler option and the catch statement can transport C++ exceptions. The /CLR compiler
option implies specification of the /EHa option. Note that the compiler does not support transporting
managed exceptions. This is because managed exceptions, which are derived from the System.Exception
class, are already objects that you can move between threads by using the facilities of the common
languange runtime.
IMPORTANT
We recommend that you specify the /EHsc compiler option and catch only C++ exceptions. You expose yourself
to a security threat if you use the /EHa or /CLR compiler option and a catch statement with an ellipsis
exception-declaration ( catch(...) ). You probably intend to use the catch statement to capture a few specific
exceptions. However, the catch(...) statement captures all C++ and SEH exceptions, including unexpected
ones that should be fatal. If you ignore or mishandle an unexpected exception, malicious code can use that
opportunity to undermine the security of your program.
Usage
The following sections describe how to transport exceptions by using the exception_ptr type, and the
current_exception , rethrow_exception , and make_exception_ptr functions.
exception_ptr type
Use an exception_ptr object to reference the current exception or an instance of a user-specified exception. In
the Microsoft implementation, an exception is represented by an EXCEPTION_RECORD structure. Each
exception_ptr object includes an exception reference field that points to a copy of the EXCEPTION_RECORD
structure that represents the exception.
When you declare an exception_ptr variable, the variable is not associated with any exception. That is, its
exception reference field is NULL. Such an exception_ptr object is called a null exception_ptr.
Use the current_exception or make_exception_ptr function to assign an exception to an exception_ptr object.
When you assign an exception to an exception_ptr variable, the variable's exception reference field points to a
copy of the exception. If there is insufficient memory to copy the exception, the exception reference field points
to a copy of a std::bad_alloc exception. If the current_exception or make_exception_ptr function cannot copy the
exception for any other reason, the function calls the terminate function to exit the current process.
Despite its name, an exception_ptr object is not itself a pointer. It does not obey pointer semantics and cannot
be used with the pointer member access ( -> ) or indirection ( * ) operators. The exception_ptr object has no
public data members or member functions.
Comparisons
You can use the equal ( == ) and not-equal ( != ) operators to compare two exception_ptr objects. The
operators do not compare the binary value (bit pattern) of the EXCEPTION_RECORD structures that represent the
exceptions. Instead, the operators compare the addresses in the exception reference field of the exception_ptr
objects. Consequently, a null exception_ptr and the NULL value compare as equal.
current_exception function
Call the current_exception function in a catch block. If an exception is in flight and the catch block can catch
the exception, the current_exception function returns an exception_ptr object that references the exception.
Otherwise, the function returns a null exception_ptr object.
Details
The current_exception function captures the exception that is in flight regardless of whether the catch
statement specifies an exception-declaration statement.
The destructor for the current exception is called at the end of the catch block if you do not rethrow the
exception. However, even if you call the current_exception function in the destructor, the function returns an
exception_ptr object that references the current exception.
Successive calls to the current_exception function return exception_ptr objects that refer to different copies of
the current exception. Consequently, the objects compare as unequal because they refer to different copies, even
though the copies have the same binary value.
SEH exceptions
If you use the /EHa compiler option, you can catch an SEH exception in a C++ catch block. The
current_exception function returns an exception_ptr object that references the SEH exception. And the
rethrow_exception function throws the SEH exception if you call it with thetransported exception_ptr object as
its argument.
The current_exception function returns a null exception_ptr if you call it in an SEH __finally termination
handler, an __except exception handler, or the __except filter expression.
A transported exception does not support nested exceptions. A nested exception occurs if another exception is
thrown while an exception is being handled. If you catch a nested exception, the
EXCEPTION_RECORD.ExceptionRecord data member points to a chain of EXCEPTION_RECORD structures that describe
the associated exceptions. The current_exception function does not support nested exceptions because it
returns an exception_ptr object whose ExceptionRecord data member is zeroed out.
If you catch an SEH exception, you must manage the memory referenced by any pointer in the
EXCEPTION_RECORD.ExceptionInformation data member array. You must guarantee that the memory is valid during
the lifetime of the corresponding exception_ptr object, and that the memory is freed when the exception_ptr
object is deleted.
You can use structured exception (SE) translator functions together with the transport exceptions feature. If an
SEH exception is translated to a C++ exception, the current_exception function returns an exception_ptr that
references the translated exception instead of the original SEH exception. The rethrow_exception function
subsequently throws the translated exception, not the original exception. For more information about SE
translator functions, see _set_se_translator.
rethrow_exception function
After you store a caught exception in an exception_ptr object, the primary thread can process the object. In
your primary thread, call the rethrow_exception function together with the exception_ptr object as its
argument. The rethrow_exception function extracts the exception from the exception_ptr object and then
throws the exception in the context of the primary thread. If the p parameter of the rethrow_exception function
is a null exception_ptr , the function throws std::bad_exception.
The extracted exception is now the current exception in the primary thread, and you can handle it as you would
any other exception. If you catch the exception, you can handle it immediately or use a throw statement to send
it to a higher level exception handler. Otherwise, do nothing and let the default system exception handler
terminate your process.
make_exception_ptr function
The make_exception_ptr function takes an instance of a class as its argument and then returns an exception_ptr
that references the instance. Usually, you specify an exception class object as the argument to the
make_exception_ptr function, although any class object can be the argument.
Calling the make_exception_ptr function is equivalent to throwing a C++ exception, catching it in a catch block,
and then calling the current_exception function to return an exception_ptr object that references the
exception. The Microsoft implementation of the make_exception_ptr function is more efficient than throwing
and then catching an exception.
An application typically does not require the make_exception_ptr function, and we discourage its use.
Example
The following example transports a standard C++ exception and a custom C++ exception from one thread to
another.
// transport_exception.cpp
// compile with: /EHsc /MD
#include <windows.h>
#include <stdio.h>
#include <exception>
#include <stdexcept>
Requirements
Header : <exception>
See also
Exception Handling
/EH (Exception Handling Model)
/clr (Common Language Runtime Compilation)
Assertion and User-Supplied Messages (C++)
3/6/2021 • 2 minutes to read • Edit Online
The C++ language supports three error handling mechanisms that help you debug your application: the #error
directive, the static_assert keyword, and the assert Macro, _assert, _wassert macro. All three mechanisms issue
error messages, and two also test software assertions. A software assertion specifies a condition that you expect
to be true at a particular point in your program. If a compile time assertion fails, the compiler issues a diagnostic
message and a compilation error. If a run-time assertion fails, the operating system issues a diagnostic message
and closes your application.
Remarks
The lifetime of your application consists of a preprocessing, compile, and run time phase. Each error handling
mechanism accesses debug information that is available during one of these phases. To debug effectively, select
the mechanism that provides appropriate information about that phase:
The #error directive is in effect at preprocessing time. It unconditionally emits a user-specified message
and causes the compilation to fail with an error. The message can contain text that is manipulated by
preprocessor directives but any resulting expression is not evaluated.
The static_assert declaration is in effect at compile time. It tests a software assertion that is represented
by a user-specified integral expression that can be converted to a Boolean. If the expression evaluates to
zero (false), the compiler issues the user-specified message and the compilation fails with an error.
The static_assert declaration is especially useful for debugging templates because template arguments
can be included in the user-specified expression.
The assert Macro, _assert, _wassert macro is in effect at run time. It evaluates a user-specified expression,
and if the result is zero, the system issues a diagnostic message and closes your application. Many other
macros, such as_ASSERT and _ASSERTE, resemble this macro but issue different system-defined or user-
defined diagnostic messages.
See also
#error Directive (C/C++)
assert Macro, _assert, _wassert
_ASSERT, _ASSERTE, _ASSERT_EXPR Macros
static_assert
_STATIC_ASSERT Macro
Templates
static_assert
3/6/2021 • 3 minutes to read • Edit Online
Tests a software assertion at compile time. If the specified constant expression is false , the compiler displays
the specified message, if one is provided, and the compilation fails with error C2338; otherwise, the declaration
has no effect.
Syntax
static_assert( constant-expression, string-literal );
Parameters
constant-expression
An integral constant expression that can be converted to a Boolean. If the evaluated expression is zero (false),
the string-literal parameter is displayed and the compilation fails with an error. If the expression is nonzero
(true), the static_assert declaration has no effect.
string-literal
An message that is displayed if the constant-expression parameter is zero. The message is a string of characters
in the base character set of the compiler; that is, not multibyte or wide characters.
Remarks
The constant-expression parameter of a static_assert declaration represents a software assertion. A software
assertion specifies a condition that you expect to be true at a particular point in your program. If the condition is
true, the static_assert declaration has no effect. If the condition is false, the assertion fails, the compiler
displays the message in string-literal parameter, and the compilation fails with an error. In Visual Studio 2017
and later, the string-literal parameter is optional.
The static_assert declaration tests a software assertion at compile time. In contrast, the assert Macro and
_assert and _wassert functions test a software assertion at run time and incur a run time cost in space or time.
The static_assert declaration is especially useful for debugging templates because template arguments can be
included in the constant-expression parameter.
The compiler examines the static_assert declaration for syntax errors when the declaration is encountered.
The compiler evaluates the constant-expression parameter immediately if it does not depend on a template
parameter. Otherwise, the compiler evaluates the constant-expression parameter when the template is
instantiated. Consequently, the compiler might issue a diagnostic message once when the declaration is
encountered, and again when the template is instantiated.
You can use the static_assert keyword at namespace, class, or block scope. (The static_assert keyword is
technically a declaration, even though it does not introduce new name into your program, because it can be
used at namespace scope.)
struct NonPOD {
NonPOD(const NonPOD &) {}
virtual ~NonPOD() {}
};
int main()
{
std::basic_string<char> bs;
}
C++20 introduces modules, a modern solution for componentization of C++ libraries and programs. A module
is a set of source code files that are compiled independently of the translation units that import them. Modules
eliminate or greatly reduce many of the problems associated with the use of header files, and also potentially
reduce compilation times. Macros, preprocessor directives, and non-exported names declared in a module are
not visible and therefore have no effect on the compilation of the translation unit that imports the module. You
can import modules in any order without concern for macro redefinitions. Declarations in the importing
translation unit do not participate in overload resolution or name lookup in the imported module. After a
module is compiled once, the results are stored in a binary file that describes all the exported types, functions
and templates. That file can be processed much faster than a header file, and can be reused by the compiler
every place where the module is imported in a project.
Modules can be used side by side with header files. A C++ source file can import modules and also #include
header files. In some cases, a header file can be imported as a module rather than textually #included by the
preprocessor. We recommend that new projects use modules rather than header files as much as possible. For
larger existing projects under active development, we suggest that you experiment with converting legacy
headers to modules to see whether you get a meaningful reduction in compilation times.
import std.core;
import std.regex;
To consume the Microsoft Standard Library module, compile your program with /EHsc and /MD options.
Basic example
The following example shows a simple module definition in a source file called Foo.ixx . The .ixx extension is
required for module interface files in Visual Studio. In this example, the interface file contains the function
definition as well as the declaration. However, the definitions can be also placed in one or more separate files (as
shown in a later example). The expor t module Foo statement indicates that this file is the primary interface for
a module called Foo . The export modifier on f() indicates that this function will be visible when Foo is
imported by another program or module. Note that the module references a namespace Bar .
#define ANSWER 42
namespace Bar
{
int f_internal() {
return ANSWER;
}
The file MyProgram.cpp uses the impor t declaration to access the name that is exported by Foo . Note that
the name Bar is visible here, but not all of its members. Also note that the macro ANSWER is not visible.
import Foo;
import std.core;
int main()
{
cout << "The result of f() is " << Bar::f() << endl; // 42
// int i = Bar::f_internal(); // C2039
// int j = ANSWER; //C2065
}
Implementing modules
You can create a module with a single interface file (.ixx) that exports names and includes implementations of all
functions and types. You can also put the implementations in one or more separate implementation files, similar
to how .h and .cpp files are used. The export keyword is used in the interface file only. An implementation file
can impor t another module, but cannot export any names. Implementation files may be named with any
extension. An interface file and the set of implementation files that back it are treated as a special kind of
translation unit called a module unit. A name that is declared in any implementation file is automatically visible
in all other files within the same module unit.
For larger modules, you can split the module into multiple module units called partitions. Each partition consists
of an interface file backed by one or more implementation files. (As of Visual Studio 2019 version 16.2,
partitions are not yet fully implemented.)
Modules, namespaces, and argument-dependent lookup
The rules for namespaces in modules are the same as in any other code. If a declaration within a namespace is
exported, the enclosing namespace (excluding non-exported members) is also implicitly exported. If a
namespace is explicitly exported, all declarations within that namespace definition are exported.
When performing argument-dependent lookup for overload resolutions in the importing translation unit, the
compiler considers functions which are declared in the same translation unit (including module interfaces) as
where the type of the function's arguments are defined.
Module partitions
NOTE
This section is provided for completeness. Partitions are not yet implemented in the Microsoft C++ compiler.
A module can be componentized into partitions, each consisting of an interface file and zero or more
implementation files. A module partition is similar to a module, except that it shares ownership of all
declarations in the entire module. All names that are exported by partition interface files are imported and re-
exported by the primary interface file. A partition's name must begin with the module name followed by a colon.
Declarations in any of the partitions are visible within the entire module. No special precautions are needed to
avoid one-definition-rule (ODR) errors. You can declare a name (function, class, etc.) in one partition and define
it in another. A partition implementation file begins like this:
module Foo:part1
To access declarations in another partition, a partition must import it, but it can only use the partition name, not
the module name:
module Foo:part2;
import :part1;
The primary interface unit must import and re-export all the module's interface partition files like this:
The primary interface unit can import partition implementation files, but cannot export them because those files
are not allowed to export any names. This enables a module to keep implementation details internal to the
module.
#include "customlib.h"
#include "anotherlib.h"
import std.core;
import MyModuleB;
You can use a traditional header file to control which modules are imported:
// MyProgram.h
import std.core;
#ifdef DEBUG_LOGGING
import std.filesystem;
#endif
NOTE
This section is informational only. Legacy imports are not yet implemented in the Microsoft C++ compiler.
Some headers are sufficiently self-contained that they are allowed to be brought in using the impor t keyword.
The main difference between an imported header and an imported module is that any preprocessor definitions
in the header are visible in the importing program immediately after the import statement. (Preprocessor
definitions in any files included by that header are not visible.)
import <vector>
import "myheader.h"
See also
module, import, export
module, import, export
4/18/2021 • 2 minutes to read • Edit Online
The module , impor t , and export declarations are available in C++20 and require the /experimental:module
compiler switch along with /std:c++latest. For more information, see Overview of modules in C++.
module
Place a module declaration at the beginning of a module implementation file to specify that the file contents
belong to the named module.
module ModuleA;
export
Use an expor t module declaration for the module's primary interface file, which must have extension .ixx :
In an interface file, use the export modifier on names that are intended to be part of the public interface:
// ModuleA.ixx
namespace Bar
{
export int f();
export double d();
double internal_f(); // not exported
}
Non-exported names are not visible to code that imports the module:
//MyProgram.cpp
int main() {
Bar::f(); // OK
Bar::d(); // OK
Bar::internal_f(); // Ill-formed: error C2065: 'internal_f': undeclared identifier
}
The export keyword may not appear in a module implementation file. When export is applied to a namespace
name, all names in the namespace are exported.
import
Use an impor t declaration to make a module's names visible in your program. The import declaration must
appear after the module declaration and after any #include directives, but before any declarations in the file.
module ModuleA;
#include "custom-lib.h"
import std.core;
import std.regex;
import ModuleB;
Remarks
Both impor t and module are treated as keywords only when they appear at the start of a logical line:
// OK:
module ;
module module-name
import :
import <
import "
import module-name
export module ;
export module module-name
export import :
export import <
export import "
export import module-name
// Error:
int i; module ;
Microsoft Specific
In Microsoft C++, the tokens impor t and module are always identifiers and never keywords when they are
used as arguments to a macro.
Example
See Also
Overview of modules in C++
Templates (C++)
3/6/2021 • 7 minutes to read • Edit Online
Templates are the basis for generic programming in C++. As a strongly-typed language, C++ requires all
variables to have a specific type, either explicitly declared by the programmer or deduced by the compiler.
However, many data structures and algorithms look the same no matter what type they are operating on.
Templates enable you to define the operations of a class or function, and let the user specify what concrete types
those operations should work on.
The above code describes a template for a generic function with a single type parameter T, whose return value
and call parameters (lhs and rhs) are all of this type. You can name a type parameter anything you like, but by
convention single upper case letters are most commonly used. T is a template parameter; the typename
keyword says that this parameter is a placeholder for a type. When the function is called, the compiler will
replace every instance of T with the concrete type argument that is either specified by the user or deduced by
the compiler. The process in which the compiler generates a class or function from a template is referred to as
template instantiation; minimum<int> is an instantiation of the template minimum<T> .
Elsewhere, a user can declare an instance of the template that is specialized for int. Assume that get_a() and
get_b() are functions that return an int:
int a = get_a();
int b = get_b();
int i = minimum<int>(a, b);
However, because this is a function template and the compiler can deduce the type of T from the arguments a
and b, you can call it just like an ordinary function:
When the compiler encounters that last statement, it generates a new function in which every occurrence of T in
the template is replaced with int :
The rules for how the compiler performs type deduction in function templates are based on the rules for
ordinary functions. For more information, see Overload Resolution of Function Template Calls.
Type parameters
In the minimum template above, note that the type parameter T is not qualified in any way until it is used in the
function call parameters, where the const and reference qualifiers are added.
There is no practical limit to the number of type parameters. Separate multiple parameters by commas:
The keyword class is equivalent to typename in this context. You can express the previous example as:
You can use the ellipsis operator (...) to define a template that takes an arbitrary number of zero or more type
parameters:
Any built-in or user-defined type can be used as a type argument. For example, you can use std::vector in the
Standard Library to store variables of type int , double , std::string, MyClass , const MyClass *, MyClass& , and
so on. The primary restriction when using templates is that a type argument must support any operations that
are applied to the type parameters. For example, if we call minimum using MyClass as in this example:
class MyClass
{
public:
int num;
std::wstring description;
};
int main()
{
MyClass mc1 {1, L"hello"};
MyClass mc2 {2, L"goodbye"};
auto result = minimum(mc1, mc2); // Error! C2678
}
A compiler error will be generated because MyClass does not provide an overload for the < operator.
There is no inherent requirement that the type arguments for any particular template all belong to the same
object hierarchy, although you can define a template that enforces such a restriction. You can combine object-
oriented techniques with templates; for example, you can store a Derived* in a vector<Base*>. Note that the
arguments must be pointers
vector<MyClass*> vec;
MyDerived d(3, L"back again", time(0));
vec.push_back(&d);
// or more realistically:
vector<shared_ptr<MyClass>> vec2;
vec2.push_back(make_shared<MyDerived>());
The basic requirements that std::vector and other standard library containers impose on elements of T is
that T be copy-assignable and copy-constructible.
Non-type parameters
Unlike generic types in other languages such as C# and Java, C++ templates support non-type parameters, also
called value parameters. For example, you can provide a constant integral value to specify the length of an array,
as with this example that is similar to the std::array class in the Standard Library:
Note the syntax in the template declaration. The size_t value is passed in as a template argument at compile
time and must be const or a constexpr expression. You use it like this:
Other kinds of values including pointers and references can be passed in as non-type parameters. For example,
you can pass in a pointer to a function or function object to customize some operation inside the template code.
Type deduction for non-type template parameters
In Visual Studio 2017 and later, in /std:c++17 mode the compiler deduces the type of a non-type template
argument that is declared with auto :
Because the Arr parameter itself has no body, its parameter names are not needed. In fact, it is an error to refer
to Arr's typename or class parameter names from within the body of MyClass2 . For this reason, Arr's type
parameter names can be omitted, as shown in this example:
In most cases the default std::allocator class is acceptable, so you use a vector like this:
vector<int> myInts;
For multiple template arguments, all arguments after the first default argument must have default arguments.
When using a template whose parameters are all defaulted, use empty angle brackets:
Template specialization
In some cases, it isn’t possible or desirable for a template to define exactly the same code for any type. For
example, you might wish to define a code path to be executed only if the type argument is a pointer, or a
std::wstring, or a type derived from a particular base class. In such cases you can define a specialization of the
template for that particular type. When a user instantiates the template with that type, the compiler uses the
specialization to generate the class, and for all other types, the compiler chooses the more general template.
Specializations in which all parameters are specialized are complete specializations. If only some of the
parameters are specialized, it is called a partial specialization.
A template can have any number of specializations as long as each specialized type parameter is unique. Only
class templates may be partially specialized. All complete and partial specializations of a template must be
declared in the same namespace as the original template.
For more information, see Template Specialization.
typename
3/6/2021 • 2 minutes to read • Edit Online
In template definitions, provides a hint to the compiler that an unknown identifier is a type. In template
parameter lists, is used to specify a type parameter.
Syntax
typename identifier;
Remarks
This keyword must be used if a name in a template definition is a qualified name that is dependent on a
template argument; it is optional if the qualified name is not dependent. For more information, see Templates
and Name Resolution.
typename can be used by any type anywhere in a template declaration or definition. It is not allowed in the base
class list, unless as a template argument to a template base class.
The typename keyword can also be used in place of class in template parameter lists. For example, the
following statements are semantically equivalent:
Example
// typename.cpp
template<class T> class X
{
typename T::Y m_y; // treat Y as a type
};
int main()
{
}
See also
Templates
Keywords
Class Templates
3/6/2021 • 6 minutes to read • Edit Online
This topic describes rules that are specific to C++ class templates.
// member_function_templates1.cpp
template<class T, int i> class MyStack
{
T* pStack;
T StackBuffer[i];
static const int cItems = i * sizeof(T);
public:
MyStack( void );
void push( const T item );
T& pop( void );
};
int main()
{
}
Note that just as with any template class member function, the definition of the class's constructor member
function includes the template argument list twice.
Member functions can themselves be function templates, specifying additional parameters, as in the following
example.
// member_templates.cpp
template<typename T>
class X
{
public:
template<typename U>
void mf(const U &u);
};
int main()
{
}
// nested_class_template1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class X
{
Y<int> yInt;
Y<char> yChar;
public:
X(int i, char c) : yInt(i), yChar(c) { }
void print()
{
cout << yInt.m_t << " " << yChar.m_t << endl;
}
};
int main()
{
X x(1, 'a');
x.print();
}
// nested_class_template2.cpp
// compile with: /EHsc
// compile with: /EHsc
#include <iostream>
using namespace std;
Y<int> y;
public:
X(T t) { y.Value() = t; }
void print() { y.print(); }
};
int main()
{
X<int>* xi = new X<int>(10);
X<char>* xc = new X<char>('c');
xi->print();
xc->print();
delete xi;
delete xc;
}
//Output:
X<T>::Y<U>::Y()
X<T>::Y<U>::Y()
10
99
X<T>::Y<U>::~Y()
X<T>::Y<U>::~Y()
Template friends
Class templates can have friends. A class or class template, function, or function template can be a friend to a
template class. Friends can also be specializations of a class template or function template, but not partial
specializations.
In the following example, a friend function is defined as a function template within the class template. This code
produces a version of the friend function for every instantiation of the template. This construct is useful if your
friend function depends on the same template parameters as the class does.
// template_friend1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
public:
Array(int sz): size(sz) {
array = new T[size];
memset(array, 0, size * sizeof(T));
}
Array(const Array& a) {
size = a.size;
array = new T[size];
memcpy_s(array, a.array, sizeof(T));
}
T& operator[](int i) {
return *(array + i);
}
void print() {
for (int i = 0; i < size; i++)
cout << *(array + i) << " ";
template<class T>
friend Array<T>* combine(Array<T>& a1, Array<T>& a2);
};
template<class T>
Array<T>* combine(Array<T>& a1, Array<T>& a2) {
Array<T>* a = new Array<T>(a1.size + a2.size);
for (int i = 0; i < a1.size; i++)
(*a)[i] = *(a1.array + i);
return a;
}
int main() {
Array<char> alpha1(26);
for (int i = 0 ; i < alpha1.Length() ; i++)
alpha1[i] = 'A' + i;
alpha1.print();
Array<char> alpha2(26);
for (int i = 0 ; i < alpha2.Length() ; i++)
alpha2[i] = 'a' + i;
alpha2.print();
Array<char>*alpha3 = combine(alpha1, alpha2);
alpha3->print();
delete alpha3;
}
//Output:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
The next example involves a friend that has a template specialization. A function template specialization is
automatically a friend if the original function template is a friend.
It is also possible to declare only the specialized version of the template as the friend, as the comment before the
friend declaration in the following code indicates. If you do this, you must put the definition of the friend
template specialization outside of the template class.
// template_friend2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
public:
Array(int sz): size(sz)
{
array = new T[size];
memset(array, 0, size * sizeof(T));
}
Array(const Array& a)
{
size = a.size;
array = new T[size];
memcpy_s(array, a.array, sizeof(T));
}
T& operator[](int i)
{
return *(array + i);
}
int Length()
{
return size;
}
void print()
{
{
for (int i = 0; i < size; i++)
{
cout << *(array + i) << " ";
}
cout << endl;
}
// If you replace the friend declaration with the int-specific
// version, only the int specialization will be a friend.
// The code in the generic f will fail
// with C2248: 'Array<T>::size' :
// cannot access private member declared in class 'Array<T>'.
//friend void f<int>(Array<int>& a);
int main()
{
Array<char> ac(10);
f(ac);
Array<int> a(10);
f(a);
}
//Output:
10 generic
10 int
The next example shows a friend class template declared within a class template. The class template is then used
as the template argument for the friend class. Friend class templates must be defined outside of the class
template in which they are declared. Any specializations or partial specializations of the friend template are also
friends of the original class template.
// template_friend3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
Factory< X<int> > XintFactory;
X<int>* x1 = XintFactory.GetNewObject(65);
X<int>* x2 = XintFactory.GetNewObject(97);
class Y
{
};
template<class T, T* pT> class X1
{
};
template<class T1, class T2 = T1> class X2
{
};
Y aY;
int main()
{
}
See also
Templates
Function Templates
3/6/2021 • 2 minutes to read • Edit Online
Class templates define a family of related classes that are based on the type arguments passed to the class upon
instantiation. Function templates are similar to class templates but define a family of functions. With function
templates, you can specify a set of functions that are based on the same code but act on different types or
classes. The following function template swaps two items:
// function_templates1.cpp
template< class T > void MySwap( T& a, T& b ) {
T c(a);
a = b;
b = c;
}
int main() {
}
This code defines a family of functions that swap the values of the arguments. From this template, you can
generate functions that will swap int and long types and also user-defined types. MySwap will even swap
classes if the class's copy constructor and assignment operator are properly defined.
In addition, the function template will prevent you from swapping objects of different types, because the
compiler knows the types of the a and b parameters at compile time.
Although this function could be performed by a nontemplated function, using void pointers, the template
version is typesafe. Consider the following calls:
int j = 10;
int k = 18;
CString Hello = "Hello, Windows!";
MySwap( j, k ); //OK
MySwap( j, Hello ); //error
The second MySwap call triggers a compile-time error, because the compiler cannot generate a MySwap function
with parameters of different types. If void pointers were used, both function calls would compile correctly, but
the function would not work properly at run time.
Explicit specification of the template arguments for a function template is allowed. For example:
// function_templates2.cpp
template<class T> void f(T) {}
int main(int j) {
f<char>(j); // Generate the specialization f(char).
// If not explicitly specified, f(int) would be deduced.
}
When the template argument is explicitly specified, normal implicit conversions are done to convert the function
argument to the type of the corresponding function template parameters. In the above example, the compiler
will convert j to type char .
See also
Templates
Function Template Instantiation
Explicit Instantiation
Explicit Specialization of Function Templates
Function Template Instantiation
3/6/2021 • 2 minutes to read • Edit Online
When a function template is first called for each type, the compiler creates an instantiation. Each instantiation is
a version of the templated function specialized for the type. This instantiation will be called every time the
function is used for the type. If you have several identical instantiations, even in different modules, only one
copy of the instantiation will end up in the executable file.
Conversion of function arguments is allowed in function templates for any argument and parameter pair where
the parameter does not depend on a template argument.
Function templates can be explicitly instantiated by declaring the template with a particular type as an
argument. For example, the following code is allowed:
// function_template_instantiation.cpp
template<class T> void f(T) { }
See also
Function Templates
Explicit Instantiation
3/6/2021 • 2 minutes to read • Edit Online
You can use explicit instantiation to create an instantiation of a templated class or function without actually using
it in your code. Because this is useful when you are creating library (.lib) files that use templates for distribution,
uninstantiated template definitions are not put into object (.obj) files.
This code explicitly instantiates MyStack for int variables and six items:
This statement creates an instantiation of MyStack without reserving any storage for an object. Code is
generated for all members.
The next line explicitly instantiates only the constructor member function:
You can explicitly instantiate function templates by using a specific type argument to re-declare them, as shown
in the example in Function Template Instantiation.
You can use the extern keyword to prevent the automatic instantiation of members. For example:
Similarly, you can mark specific members as being external and not instantiated:
You can use the extern keyword to keep the compiler from generating the same instantiation code in more
than one object module. You must instantiate the template function by using the specified explicit template
parameters in at least one linked module if the function is called, or you will get a linker error when the program
is built.
NOTE
The extern keyword in the specialization only applies to member functions defined outside of the body of the class.
Functions defined inside the class declaration are considered inline functions and are always instantiated.
See also
Function Templates
Explicit Specialization of Function Templates
3/6/2021 • 2 minutes to read • Edit Online
With a function template, you can define special behavior for a specific type by providing an explicit
specialization (override) of the function template for that type. For example:
This declaration enables you to define a different function for double variables. Like non-template functions,
standard type conversions (such as promoting a variable of type float to double ) are applied.
Example
// explicit_specialization.cpp
template<class T> void f(T t)
{
};
See also
Function Templates
Partial Ordering of Function Templates (C++)
3/6/2021 • 2 minutes to read • Edit Online
Multiple function templates that match the argument list of a function call can be available. C++ defines a
partial ordering of function templates to specify which function should be called. The ordering is partial because
there can be some templates that are considered equally specialized.
The compiler chooses the most specialized template function available from the possible matches. For example,
if a function template takes a type T and another function template that takes T* is available, the T* version
is said to be more specialized. It's preferred over the generic T version whenever the argument is a pointer
type, even though both would be allowable matches.
Use the following process to determine if one function template candidate is more specialized:
1. Consider two function templates, T1 and T2.
2. Replace the parameters in T1 with a hypothetical unique type X.
3. With the parameter list in T1, see if T2 is a valid template for that parameter list. Ignore any implicit
conversions.
4. Repeat the same process with T1 and T2 reversed.
5. If one template is a valid template argument list for the other template, but the converse isn't true, then
that template is considered to be less specialized than the other template. If by using the previous step,
both templates form valid arguments for each other, then they're considered to be equally specialized,
and an ambiguous call results when you attempt to use them.
6. Using these rules:
a. A template specialization for a specific type is more specialized than one taking a generic type
argument.
b. A template taking only T* is more specialized than one taking only T , because a hypothetical
type X* is a valid argument for a T template argument, but X is not a valid argument for a T*
template argument.
c. const Tis more specialized than T , because const X is a valid argument for a T template
argument, but X is not a valid argument for a const T template argument.
d. const T* is more specialized than T* , because const X* is a valid argument for a T* template
argument, but X* is not a valid argument for a const T* template argument.
Example
The following sample works as specified in the standard:
// partial_ordering_of_function_templates.cpp
// compile with: /EHsc
#include <iostream>
int main() {
int i =0;
const int j = 0;
int *pi = &i;
const int *cpi = &j;
Output
See also
Function Templates
Member Function Templates
3/6/2021 • 2 minutes to read • Edit Online
The term member template refers to both member function templates and nested class templates. Member
function templates are template functions that are members of a class or class template.
Member functions can be function templates in several contexts. All functions of class templates are generic but
are not referred to as member templates or member function templates. If these member functions take their
own template arguments, they are considered to be member function templates.
// member_function_templates.cpp
struct X
{
template <class T> void mf(T* t) {}
};
int main()
{
int i;
X* x = new X();
x->mf(&i);
}
// member_function_templates2.cpp
template<typename T>
class X
{
public:
template<typename U>
void mf(const U &u)
{
}
};
int main()
{
}
int main()
{
}
// templated_user_defined_conversions.cpp
template <class T>
struct S
{
template <class U> operator S<U>()
{
return S<U>();
}
};
int main()
{
S<int> s1;
S<long> s2 = s1; // Convert s1 using UDC and copy constructs S<long>.
}
See also
Function Templates
Template Specialization (C++)
3/6/2021 • 5 minutes to read • Edit Online
Class templates can be partially specialized, and the resulting class is still a template. Partial specialization allows
template code to be partially customized for specific types in situations, such as:
A template has multiple types and only some of them need to be specialized. The result is a template
parameterized on the remaining types.
A template has only one type, but a specialization is needed for pointer, reference, pointer to member, or
function pointer types. The specialization itself is still a template on the type pointed to or referenced.
struct S{};
int main() {
printf_s("PTS<S>::IsPointer == %d PTS<S>::IsPointerToDataMember == %d\n",
PTS<S>::IsPointer, PTS<S>:: IsPointerToDataMember);
printf_s("PTS<S*>::IsPointer == %d PTS<S*>::IsPointerToDataMember ==%d\n"
, PTS<S*>::IsPointer, PTS<S*>:: IsPointerToDataMember);
printf_s("PTS<int S::*>::IsPointer == %d PTS"
"<int S::*>::IsPointerToDataMember == %d\n",
PTS<int S::*>::IsPointer, PTS<int S::*>::
IsPointerToDataMember);
}
PTS<S>::IsPointer == 0 PTS<S>::IsPointerToDataMember == 0
PTS<S*>::IsPointer == 1 PTS<S*>::IsPointerToDataMember ==0
PTS<int S::*>::IsPointer == 0 PTS<int S::*>::IsPointerToDataMember == 1
// partial_specialization_of_class_templates2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
public:
Bag() : elem(0), size(0), max_size(1) {}
void add(T t) {
T* tmp;
if (size + 1 >= max_size) {
max_size *= 2;
tmp = new T [max_size];
for (int i = 0; i < size; i++)
tmp[i] = elem[i];
tmp[size++] = t;
delete[] elem;
elem = tmp;
}
else
elem[size++] = t;
}
void print() {
for (int i = 0; i < size; i++)
cout << elem[i] << " ";
cout << endl;
}
};
public:
Bag() : elem(0), size(0), max_size(1) {}
void add(T* t) {
T* tmp;
if (t == NULL) { // Check for NULL
cout << "Null pointer!" << endl;
return;
}
void print() {
for (int i = 0; i < size; i++)
cout << elem[i] << " ";
cout << endl;
}
};
int main() {
Bag<int> xi;
Bag<char> xc;
Bag<int*> xp; // Uses partial specialization for pointer types.
xi.add(10);
xi.add(9);
xi.add(8);
xi.print();
xc.add('a');
xc.add('b');
xc.add('c');
xc.print();
10 9 8
a b c
Null pointer!
3 87 8 100
// partial_specialization_of_class_templates3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void print() {
for (int i = 0; i < size; i++)
cout << "{" << keys[i] << ", " << values[i] << "}" << endl;
}
};
void sort() {
// Sort method is defined.
int smallest = 0;
for (int i = 0; i < size - 1; i++) {
for (int j = i; j < size; j++) {
if (keys[j] < keys[smallest])
smallest = j;
}
swap(keys[i], keys[smallest]);
swap(values[i], values[smallest]);
}
}
void print() {
for (int i = 0; i < size; i++)
cout << "{" << keys[i] << ", " << values[i] << "}" << endl;
}
};
int main() {
Dictionary<char*, char*>* dict = new Dictionary<char*, char*>(10);
dict->print();
dict->add("apple", "fruit");
dict->add("banana", "fruit");
dict->add("dog", "animal");
dict->print();
{apple, fruit}
{banana, fruit}
{dog, animal}
{100, apple}
{101, banana}
{103, dog}
{89, cat}
Sorted list:
{89, cat}
{100, apple}
{101, banana}
{103, dog}
Templates and Name Resolution
3/6/2021 • 2 minutes to read • Edit Online
T::myType
N::T
A const or volatile type for which the base type is a dependent type:
const T
See also
Templates
Name Resolution for Dependent Types
3/6/2021 • 2 minutes to read • Edit Online
Use typename for qualified names in template definitions to tell the compiler that the given qualified name
identifies a type. For more information, see typename.
// template_name_resolution1.cpp
#include <stdio.h>
template <class T> class X
{
public:
void f(typename T::myType* mt) {}
};
class Yarg
{
public:
struct myType { };
};
int main()
{
X<Yarg> x;
x.f(new Yarg::myType());
printf("Name resolved by using typename keyword.");
}
Name lookup for dependent names examines names from both the context of the template definition—in the
following example, this context would find myFunction(char) —and the context of the template instantiation.In
the following example, the template is instantiated in main; therefore, the MyNamespace::myFunction is visible
from the point of instantiation and is picked as the better match. If MyNamespace::myFunction were renamed,
myFunction(char) would be called instead.
All names are resolved as if they were dependent names. Nevertheless, we recommend that you use fully
qualified names if there is any possible conflict.
// template_name_resolution2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void myFunction(char)
{
cout << "Char myFunction" << endl;
}
namespace MyNamespace
{
void myFunction(int)
{
cout << "Int MyNamespace::myFunction" << endl;
}
};
int main()
{
Class1<int>* c1 = new Class1<int>(100);
}
Output
Int MyNamespace::myFunction
Template Disambiguation
Visual Studio 2012 enforces the C++98/03/11 standard rules for disambiguation with the "template" keyword.
In the following example, Visual Studio 2010 would accept both the nonconforming lines and the conforming
lines. Visual Studio 2012 accepts only the conforming lines.
#include <iostream>
#include <ostream>
#include <typeinfo>
using namespace std;
int main() {
cout << typeid(Container<int, Allocator<float>>::AX).name() << endl;
}
Conformance with the disambiguation rules is required because, by default, C++ assumes that AY::Rebind isn't
a template, and so the compiler interprets the following " < " as a less-than. It has to know that Rebind is a
template so that it can correctly parse " < " as an angle bracket.
See also
Name Resolution
Name Resolution for Locally Declared Names
3/6/2021 • 3 minutes to read • Edit Online
The template's name itself can be referred to with or without the template arguments. In the scope of a class
template, the name itself refers to the template. In the scope of a template specialization or partial specialization,
the name alone refers to the specialization or partial specialization. Other specializations or partial
specializations of the template can also be referenced, with the appropriate template arguments.
// template_name_resolution3.cpp
// compile with: /c
template <class T> class A {
A* a1; // A refers to A<T>
A<int>* a2; // A<int> refers to a specialization of A.
A<T*>* a3; // A<T*> refers to the partial specialization A<T*>.
};
// template_name_resolution4.cpp
// compile with: /EHsc
template <class T>
class Base1 {};
int main() {
// Derived1<int> d;
}
// template_name_resolution5.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main() {
C<int> c;
c.f();
}
Z::Z()
// template_name_resolution6.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
namespace NS {
void g() { cout << "NS::g" << endl; }
int main() {
NS::C<int> c;
c.f();
}
C<T>::g
// template_name_resolution7.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct B {
int i;
void print() { cout << "Base" << endl; }
};
int main() {
C<int, 1> c;
c.f();
cout << c.i << endl;
}
Base
1
See also
Name Resolution
Overload Resolution of Function Template Calls
3/6/2021 • 2 minutes to read • Edit Online
A function template can overload nontemplate functions of the same name. In this scenario, function calls are
resolved by first using template argument deduction to instantiate the function template with a unique
specialization. If template argument deduction fails, the other function overloads are considered to resolve the
call. These other overloads, also known as the candidate set, include nontemplate functions and other
instantiated function templates. If template argument deduction succeeds, then the generated function is
compared with the other functions to determine the best match, following the rules for overload resolution. For
more information, see Function Overloading.
// template_name_resolution9.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
f(1, 1); // Equally good match; choose the nontemplate function.
f('a', 1); // Chooses the template function.
f<int, int>(2, 2); // Template arguments explicitly specified.
}
f(int, int)
void f(T1, T2)
void f(T1, T2)
int main()
{
long l = 0;
int i = 0;
// Call the template function f(long, int) because f(int, int)
// would require a conversion from long to int.
f(l, i);
}
See also
Name Resolution
typename
Source code organization (C++ Templates)
3/6/2021 • 3 minutes to read • Edit Online
When defining a class template, you must organize the source code in such a way that the member definitions
are visible to the compiler when it needs them. You have the choice of using the inclusion model or the explicit
instantiation model. In the inclusion model, you include the member definitions in every file that uses a
template. This approach is simplest and provides maximum flexibility in terms of what concrete types can be
used with your template. Its disadvantage is that it can increase compilation times. The impact can be significant
if a project and/or the included files themselves are large. With the explicit instantiation approach, the template
itself instantiates concrete classes or class members for specific types. This approach can speed up compilation
times, but it limits usage to only those classes that the template implementer has enabled ahead of time. In
general, we recommend that you use the inclusion model unless the compilation times become a problem.
Background
Templates are not like ordinary classes in the sense that the compiler does not generate object code for a
template or any of its members. There is nothing to generate until the template is instantiated with concrete
types. When the compiler encounters a template instantiation such as MyClass<int> mc; and no class with that
signature exists yet, it generates a new class. It also attempts to generate code for any member functions that
are used. If those definitions are in a file that is not #included, directly or indirectly, in the .cpp file that is being
compiled, the compiler can't see them. From the compiler's point of view, this isn't necessarily an error because
the functions may be defined in another translation unit, in which case the linker will find them. If the linker does
not find that code, it raises an unresolved external error.
T& operator[](int i)
{
return arr[i];
}
};
#endif
With this approach, the compiler has access to the complete template definition and can instantiate templates
on-demand for any type. It is simple and relatively easy to maintain. However, the inclusion model does have a
cost in terms of compilation times. This cost can be significant in large programs, especially if the template
header itself #includes other headers. Every .cpp file that #includes the header will get its own copy of the
function templates and all the definitions. The linker will generally be able to sort things out so that you do not
end up with multiple definitions for a function, but it takes time to do this work. In smaller programs that extra
compilation time is probably not significant.
//MyArray.cpp
#include <iostream>
#include "MyArray.h"
In the previous example, the explicit instantiations are at the bottom of the .cpp file. A MyArray may be used
only for double or String types.
NOTE
In C++11 the export keyword was deprecated in the context of template definitions. In practical terms this has little
impact because most compilers never supported it.
Event handling
3/6/2021 • 2 minutes to read • Edit Online
Event handling is primarily supported for COM classes (C++ classes that implement COM objects, typically
using ATL classes or the coclass attribute). For more information, see Event handling in COM.
Event handling is also supported for native C++ classes (C++ classes that don't implement COM objects).
Native C++ event handling support is deprecated and will be removed in a future release. For more
information, see Event handling in native C++.
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Event handling supports both single- and multithreaded usage. It protects data from simultaneous multithread
access. You can derive subclasses from event source or receiver classes. These subclasses support extended
event sourcing and receiving.
The Microsoft C++ compiler includes attributes and keywords for declaring events and event handlers. The
event attributes and keywords can be used in CLR programs and in native C++ programs.
A RT IC L E DESC RIP T IO N
See also
C++ language reference
Keywords
__event keyword
3/6/2021 • 3 minutes to read • Edit Online
Declares an event.
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Syntax
__event member-function-declarator ;
__event __interface interface-specifier ;
__event data-member-declarator ;
Remarks
The Microsoft-specific keyword __event can be applied to a member function declaration, an interface
declaration, or a data member declaration. However, you can't use the __event keyword to qualify a member of
a nested class.
Depending on whether your event source and receiver are native C++, COM, or managed (.NET Framework),
you can use the following constructs as events:
N AT IVE C ++ C OM M A N A GED ( . N ET F RA M EW O RK )
- interface -
- - data member
Use __hook in an event receiver to associate a handler member function with an event member function. After
you create an event with the __event keyword, all event handlers hooked to that event afterward get called
when the event is called.
An __event member function declaration can't have a definition; a definition is implicitly generated, so the
event member function can be called as if it were any ordinary member function.
NOTE
A templated class or struct can't contain events.
Native events
Native events are member functions. The return type is typically HRESULT or void , but can be any integral type,
including an enum . When an event uses an integral return type, an error condition is defined when an event
handler returns a nonzero value. In this case, the event that's raised calls the other delegates.
COM events
COM events are interfaces. The parameters of a member function in an event source interface should be in
parameters, but it isn't rigorously enforced. It's because an out parameter isn't useful when multicasting. A level
1 warning is issued if you use an out parameter.
The return type is typically HRESULT or void , but can be any integral type, including enum . When an event uses
an integral return type and an event handler returns a nonzero value, it's an error condition. The event being
raised aborts the calls to the other delegates. The compiler automatically marks an event source interface as a
source in the generated IDL.
The __interface keyword is always required after __event for a COM event source.
Managed events
For information on coding events in the new syntax, see event.
Managed events are data members or member functions. When used with an event, the return type of a
delegate must be compliant with the Common Language Specification. The return type of the event handler
must match the return type of the delegate. For more information on delegates, see Delegates and Events. If a
managed event is a data member, its type must be a pointer to a delegate.
In the .NET Framework, you can treat a data member as if it were a method itself (that is, the Invoke method of
its corresponding delegate). To do so, predefine the delegate type for declaring a managed event data member.
In contrast, a managed event method implicitly defines the corresponding managed delegate if it isn't already
defined. For example, you can declare an event value such as OnClick as an event as follows:
When implicitly declaring a managed event, you can specify add and remove accessors that get called when
event handlers are added or removed. You can also define the member function that calls (raises) the event from
outside the class.
[ dual, uuid("00000000-0000-0000-0000-000000000002") ]
__interface IEventSource {
[id(1)] HRESULT MyEvent();
};
[ coclass, uuid("00000000-0000-0000-0000-000000000003"), event_source(com) ]
class CSource : public IEventSource {
public:
__event __interface IEventSource;
HRESULT FireEvent() {
__raise MyEvent();
return S_OK;
}
};
See also
Keywords
Event handling
event_source
event_receiver
__hook
__unhook
__raise
__hook keyword
3/6/2021 • 2 minutes to read • Edit Online
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Syntax
long __hook(
&SourceClass::EventMethod,
source,
&ReceiverClass::HandlerMethod
[, receiver = this]
);
long __hook(
interface,
source
);
Parameters
&SourceClass::EventMethod
A pointer to the event method to which you hook the event handler method:
Native C++ events: SourceClass is the event source class and EventMethod is the event.
COM events: SourceClass is the event source interface and EventMethod is one of its methods.
Managed events: SourceClass is the event source class and EventMethod is the event.
interface
The interface name being hooked to receiver , only for COM event receivers in which the layout_dependent
parameter of the event_receiver attribute is true .
source
A pointer to an instance of the event source. Depending on the code type specified in event_receiver , source
can be one of these types:
A native event source object pointer.
An IUnknown -based pointer (COM source).
A managed object pointer (for managed events).
&ReceiverClass::HandlerMethod
A pointer to the event handler method to be hooked to an event. The handler is specified as a method of a class
or a reference to the same. If you don't specify the class name, __hook assumes the class is the one it's called
from.
Native C++ events: ReceiverClass is the event receiver class and HandlerMethod is the handler.
COM events: ReceiverClass is the event receiver interface and HandlerMethod is one of its handlers.
Managed events: ReceiverClass is the event receiver class and HandlerMethod is the handler.
receiver
(Optional) A pointer to an instance of the event receiver class. If you don't specify a receiver, the default is the
receiver class or structure in which __hook is called.
Usage
Can be use in any function scope, including main, outside the event receiver class.
Remarks
Use the intrinsic function __hook in an event receiver to associate or hook a handler method with an event
method. The specified handler is then called when the source raises the specified event. You can hook several
handlers to a single event or hook several events to a single handler.
There are two forms of __hook . You can use the first (four-argument) form in most cases, specifically, for COM
event receivers in which the layout_dependent parameter of the event_receiver attribute is false .
In these cases, you don't need to hook all methods in an interface before firing an event on one of the methods.
You only need to hook the method handling the event. You can use the second (two-argument) form of __hook
only for a COM event receiver in which layout_dependent = true .
__hook returns a long value. A nonzero return value indicates that an error has occurred (managed events
throw an exception).
The compiler checks for the existence of an event and that the event signature agrees with the delegate
signature.
You can call __hook and __unhook outside the event receiver, except for COM events.
An alternative to using __hook is to use the += operator.
For information on coding managed events in the new syntax, see event .
NOTE
A templated class or struct cannot contain events.
Example
See Event handling in native C++ and Event handling in COM for samples.
See also
Keywords
Event handling
event_source
event_receiver
__event
__unhook
__raise
__raise keyword
3/6/2021 • 2 minutes to read • Edit Online
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Syntax
__raise method-declarator ;
Remarks
From managed code, an event can only be raised from within the class where it's defined. For more information,
see event .
The keyword __raise causes an error to be emitted if you call a non-event.
NOTE
A templated class or struct cannot contain events.
Example
// EventHandlingRef_raise.cpp
struct E {
__event void func1();
void func1(int) {}
void func2() {}
void b() {
__raise func1();
__raise func1(1); // C3745: 'int Event::bar(int)':
// only an event can be 'raised'
__raise func2(); // C3745
}
};
int main() {
E e;
__raise e.func1();
__raise e.func1(1); // C3745
__raise e.func2(); // C3745
}
See also
Keywords
Event handling
__event
__hook
__unhook
Component extensions for .NET and UWP
__unhook keyword
3/6/2021 • 2 minutes to read • Edit Online
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Syntax
long __unhook(
&SourceClass::EventMethod,
source,
&ReceiverClass::HandlerMethod
[, receiver = this]
);
long __unhook(
interface,
source
);
long __unhook(
source
);
Parameters
&SourceClass::EventMethod
A pointer to the event method from which you unhook the event handler method:
Native C++ events: SourceClass is the event source class and EventMethod is the event.
COM events: SourceClass is the event source interface and EventMethod is one of its methods.
Managed events: SourceClass is the event source class and EventMethod is the event.
interface
The interface name being unhooked from receiver, only for COM event receivers in which the layout_dependent
parameter of the event_receiver attribute is true .
source
A pointer to an instance of the event source. Depending on the code type specified in event_receiver , source
can be one of these types:
A native event source object pointer.
An IUnknown -based pointer (COM source).
A managed object pointer (for managed events).
&ReceiverClass::HandlerMethod A pointer to the event handler method to be unhooked from an event. The
handler is specified as a method of a class or a reference to the same; if you don't specify the class name,
__unhook assumes the class to be the one in which it's called.
Native C++ events: ReceiverClass is the event receiver class and HandlerMethod is the handler.
COM events: ReceiverClass is the event receiver interface and HandlerMethod is one of its handlers.
Managed events: ReceiverClass is the event receiver class and HandlerMethod is the handler.
receiver (optional) A pointer to an instance of the event receiver class. If you don't specify a receiver, the default
is the receiver class or structure in which __unhook is called.
Usage
Can be use in any function scope, including main , outside the event receiver class.
Remarks
Use the intrinsic function __unhook in an event receiver to disassociate or "unhook" a handler method from an
event method.
There are three forms of __unhook . You can use the first (four-argument) form in most cases. You can use the
second (two-argument) form of __unhook only for a COM event receiver; it unhooks the entire event interface.
You can use the third (one-argument) form to unhook all delegates from the specified source.
A nonzero return value indicates that an error has occurred (managed events will throw an exception).
If you call __unhook on an event and event handler that aren't already hooked, it will have no effect.
At compile time, the compiler verifies that the event exists and does parameter type checking with the specified
handler.
You can call __hook and __unhook outside the event receiver, except for COM events.
An alternative to using __unhook is to use the -= operator.
For information on coding managed events in the new syntax, see event.
NOTE
A templated class or struct cannot contain events.
Example
See Event Handling in Native C++ and Event Handling in COM for samples.
See also
Keywords
event_source
event_receiver
__event
__hook
__raise
Event handling in native C++
3/6/2021 • 2 minutes to read • Edit Online
In native C++ event handling, you set up an event source and event receiver using the event_source and
event_receiver attributes, respectively, specifying type = native . These attributes allow the classes they're
applied on to fire events and handle events in a native, non-COM context.
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Declaring events
In an event source class, use the __event keyword on a method declaration to declare the method as an event.
Make sure to declare the method, but don't define it. If you do, it generates a compiler error, because the
compiler defines the method implicitly when it's made into an event. Native events can be methods with zero or
more parameters. The return type can be void or any integral type.
Firing events
To fire an event, call the method declared as an event in the event source class. If handlers have been hooked to
the event, the handlers will be called.
Native C++ event code
The following example shows how to fire an event in native C++. To compile and run the example, refer to the
comments in the code. To build the code in the Visual Studio IDE, verify that the /permissive- option is turned
off.
Example
Code
// evh_native.cpp
// compile by using: cl /EHsc /W3 evh_native.cpp
#include <stdio.h>
[event_source(native)]
class CSource {
public:
__event void MyEvent(int nValue);
};
[event_receiver(native)]
class CReceiver {
public:
void MyHandler1(int nValue) {
printf_s("MyHandler1 was called with value %d.\n", nValue);
}
int main() {
CSource source;
CReceiver receiver;
receiver.hookEvent(&source);
__raise source.MyEvent(123);
receiver.unhookEvent(&source);
}
Output
See also
Event handling
Event handling in COM
3/6/2021 • 4 minutes to read • Edit Online
In COM event handling, you set up an event source and event receiver using the event_source and
event_receiver attributes, respectively, specifying type = com . These attributes inject appropriate code for
custom, dispatch, and dual interfaces. The injected code allows the attributed classes to fire events and handle
events through COM connection points.
NOTE
Event attributes in native C++ are incompatible with Standard C++. They don't compile when you specify /permissive-
conformance mode.
Declaring events
In an event source class, use the __event keyword on an interface declaration to declare that interface's
methods as events. The events of that interface are fired when you call them as interface methods. Methods on
event interfaces can have zero or more parameters (which should all be in parameters). The return type can be
void or any integral type.
NOTE
Typically, there are two techniques to allow a COM event receiver to access event source interface definitions. The first, as
shown below, is to share a common header file. The second is to use #import with the embedded_idl import qualifier, so
that the event source type library is written to the .tlh file with the attribute-generated code preserved.
Firing events
To fire an event, call a method in the interface declared with the __event keyword in the event source class. If
handlers have been hooked to the event, the handlers will be called.
COM event code
The following example shows how to fire an event in a COM class. To compile and run the example, refer to the
comments in the code.
// evh_server.h
#pragma once
[ dual, uuid("00000000-0000-0000-0000-000000000001") ]
__interface IEvents {
[id(1)] HRESULT MyEvent([in] int value);
};
[ dual, uuid("00000000-0000-0000-0000-000000000002") ]
__interface IEventSource {
[id(1)] HRESULT FireEvent();
};
// evh_server.cpp
// compile with: /LD
// post-build command: Regsvr32.exe /s evh_server.dll
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>
#include "evh_server.h"
HRESULT FireEvent() {
__raise MyEvent(123);
return S_OK;
}
};
[ module(name="EventReceiver") ];
[ event_receiver(com) ]
class CReceiver {
public:
HRESULT MyHandler1(int nValue) {
printf_s("MyHandler1 was called with value %d.\n", nValue);
return S_OK;
}
int main() {
// Create COM object
CoInitialize(NULL);
{
IEventSource* pSource = 0;
HRESULT hr = CoCreateInstance(__uuidof(CSource), NULL, CLSCTX_ALL, __uuidof(IEventSource),
(void **) &pSource);
if (FAILED(hr)) {
return -1;
}
Output
[coclass, event_source(com)]
class CSource : public IEventSource {
public:
__event __interface IEvents;
HRESULT FireEvent() {
MyEvent1(123);
MyEvent2(123);
return S_OK;
}
};
Then, in the event receiver, any handler hooked to a method in IEventSource must match its name and
signature, as follows:
See also
Event handling
Microsoft-specific modifiers
3/6/2021 • 2 minutes to read • Edit Online
Microsoft-specific keywords
Many of the Microsoft-specific keywords can be used to modify declarators to form derived types. For more
information about declarators, see Declarators.
See also
Microsoft-Specific Modifiers
__based Grammar
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Based addressing is useful when you need precise control over the segment in which objects are allocated (static
and dynamic based data).
The only form of based addressing acceptable in 32-bit and 64-bit compilations is "based on a pointer" that
defines a type that contains a 32-bit or 64-bit displacement to a 32-bit or 64-bit base or based on void .
Grammar
based-range-modifier: __based( base-expression )
base-expression: based-variablebased-abstract-declaratorsegment-namesegment-cast
based-variable: identifier
based-abstract-declarator: abstract-declarator
base-type: type-name
END Microsoft Specific
See also
Based Pointers
Based Pointers (C++)
3/6/2021 • 2 minutes to read • Edit Online
The __based keyword allows you to declare pointers based on pointers (pointers that are offsets from existing
pointers). The __based keyword is Microsoft-specific.
Syntax
type __based( base ) declarator
Remarks
Pointers based on pointer addresses are the only form of the __based keyword valid in 32-bit or 64-bit
compilations. For the Microsoft 32-bit C/C++ compiler, a based pointer is a 32-bit offset from a 32-bit pointer
base. A similar restriction holds for 64-bit environments, where a based pointer is a 64-bit offset from the 64-bit
base.
One use for pointers based on pointers is for persistent identifiers that contain pointers. A linked list that
consists of pointers based on a pointer can be saved to disk, then reloaded to another place in memory, with the
pointers remaining valid. For example:
// based_pointers1.cpp
// compile with: /c
void *vpBuffer;
struct llist_t {
void __based( vpBuffer ) *vpData;
struct llist_t __based( vpBuffer ) *llNext;
};
The pointer vpBuffer is assigned the address of memory allocated at some later point in the program. The
linked list is relocated relative to the value of vpBuffer .
NOTE
Persisting identifiers containing pointers can also be accomplished by using memory-mapped files.
When dereferencing a based pointer, the base must be either explicitly specified or implicitly known through the
declaration.
For compatibility with previous versions, _based is a synonym for __based unless compiler option /Za (Disable
language extensions) is specified.
Example
The following code demonstrates changing a based pointer by changing its base.
// based_pointers2.cpp
// compile with: /EHsc
#include <iostream>
pBased = &a2[0];
1
2
10
11
See also
Keywords
alloc_text
Calling Conventions
3/6/2021 • 2 minutes to read • Edit Online
The Visual C/C++ compiler provides several different conventions for calling internal and external functions.
Understanding these different approaches can help you debug your program and link your code with assembly-
language routines.
The topics on this subject explain the differences between the calling conventions, how arguments are passed,
and how values are returned by functions. They also discuss naked function calls, an advanced feature that
enables you to write your own prolog and epilog code.
For information on calling conventions for x64 processors, see Calling Convention.
See also
Microsoft-Specific Modifiers
Argument Passing and Naming Conventions
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The Microsoft C++ compilers allow you to specify conventions for passing arguments and return values
between functions and callers. Not all conventions are available on all supported platforms, and some
conventions use platform-specific implementations. In most cases, keywords or compiler switches that specify
an unsupported convention on a particular platform are ignored, and the platform default convention is used.
On x86 platforms, all arguments are widened to 32 bits when they are passed. Return values are also widened to
32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register
pair. Larger structures are returned in the EAX register as pointers to hidden return structures. Parameters are
pushed onto the stack from right to left. Structures that are not PODs will not be returned in registers.
The compiler generates prolog and epilog code to save and restore the ESI, EDI, EBX, and EBP registers, if they
are used in the function.
NOTE
When a struct, union, or class is returned from a function by value, all definitions of the type need to be the same, else the
program may fail at runtime.
For information on how to define your own function prolog and epilog code, see Naked Function Calls.
For information about the default calling conventions in code that targets x64 platforms, see x64 Calling
Convention. For information about calling convention issues in code that targets ARM platforms, see Common
Visual C++ ARM Migration Issues.
The following calling conventions are supported by the Visual C/C++ compiler.
K EY W O RD STA C K C L EA N UP PA RA M ET ER PA SSIN G
See also
Calling Conventions
__cdecl
3/6/2021 • 2 minutes to read • Edit Online
__cdecl is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller,
it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it
requires each function call to include stack cleanup code. The following list shows the implementation of this
calling convention. The __cdecl modifier is Microsoft-specific.
EL EM EN T IM P L EM EN TAT IO N
Stack-maintenance responsibility Calling function pops the arguments from the stack.
NOTE
For related information, see Decorated Names.
Place the __cdecl modifier before a variable or a function name. Because the C naming and calling conventions
are the default, the only time you must use __cdecl in x86 code is when you have specified the /Gv
(vectorcall), /Gz (stdcall), or /Gr (fastcall) compiler option. The /Gd compiler option forces the __cdecl calling
convention.
On ARM and x64 processors, __cdecl is accepted but typically ignored by the compiler. By convention on ARM
and x64, arguments are passed in registers when possible, and subsequent arguments are passed on the stack.
In x64 code, use __cdecl to override the /Gv compiler option and use the default x64 calling convention.
For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have
to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention
specified during declaration is assumed at the point of definition. Given this class definition:
struct CMyClass {
void __cdecl mymethod();
};
this:
is equivalent to this:
Example
In the following example, the compiler is instructed to use C naming and calling conventions for the system
function.
See also
Argument Passing and Naming Conventions
Keywords
__clrcall
3/6/2021 • 3 minutes to read • Edit Online
Specifies that a function can only be called from managed code. Use __clrcall for all virtual functions that will
only be called from managed code. However this calling convention cannot be used for functions that will be
called from native code. The __clrcall modifier is Microsoft-specific.
Use __clrcall to improve performance when calling from a managed function to a virtual managed function or
from managed function to managed function through pointer.
Entry points are separate, compiler-generated functions. If a function has both native and managed entry points,
one of them will be the actual function with the function implementation. The other function will be a separate
function (a thunk) that calls into the actual function and lets the common language runtime perform PInvoke.
When marking a function as __clrcall , you indicate the function implementation must be MSIL and that the
native entry point function will not be generated.
When taking the address of a native function if __clrcall is not specified, the compiler uses the native entry
point. __clrcall indicates that the function is managed and there is no need to go through the transition from
managed to native. In that case the compiler uses the managed entry point.
When /clr (not /clr:pure or /clr:safe ) is used and __clrcall is not used, taking the address of a function
always returns the address of the native entry point function. When __clrcall is used, the native entry point
function is not created, so you get the address of the managed function, not an entry point thunk function. For
more information, see Double Thunking. The /clr :pure and /clr :safe compiler options are deprecated in Visual
Studio 2015 and unsupported in Visual Studio 2017.
/clr (Common Language Runtime Compilation) implies that all functions and function pointers are __clrcall and
the compiler will not permit a function inside the compiland to be marked anything other than __clrcall . When
/clr :pure is used, __clrcall can only be specified on function pointers and external declarations.
You can directly call __clrcall functions from existing C++ code that was compiled by using /clr as long as that
function has an MSIL implementation. __clrcall functions cannot be called directly from functions that have
inline asm and call CPU-specific intrinisics, for example, even if those functions are compiled with /clr .
__clrcall function pointers are only meant to be used in the application domain in which they were created.
Instead of passing __clrcall function pointers across application domains, use CrossAppDomainDelegate. For
more information, see Application Domains and Visual C++.
Examples
Note that when a function is declared with __clrcall , code will be generated when needed; for example, when
function is called.
// clrcall2.cpp
// compile with: /clr
using namespace System;
int __clrcall Func1() {
Console::WriteLine("in Func1");
return 0;
}
// Func1 hasn't been used at this point (code has not been generated),
// so runtime returns the adddress of a stub to the function
int (__clrcall *pf)() = &Func1;
int main() {
if (&Func1 == pf)
Console::WriteLine("&Func1 == pf, comparison succeeds");
else
Console::WriteLine("&Func1 != pf, comparison fails");
// even though comparison fails, stub and function call are correct
pf();
Func1();
}
in Func1
&Func1 != pf, comparison fails
in Func1
in Func1
The following sample shows that you can define a function pointer, such that, you declare that the function
pointer will only be invoked from managed code. This allows the compiler to directly call the managed function
and avoid the native entry point (double thunk issue).
// clrcall3.cpp
// compile with: /clr
void Test() {
System::Console::WriteLine("in Test");
}
int main() {
void (*pTest)() = &Test;
(*pTest)();
See also
Argument Passing and Naming Conventions
Keywords
__stdcall
3/6/2021 • 2 minutes to read • Edit Online
The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the
compiler makes vararg functions __cdecl . Functions that use this calling convention require a function
prototype. The __stdcall modifier is Microsoft-specific.
Syntax
return-type __stdcall function-name[ ( argument-list ) ]
Remarks
The following list shows the implementation of this calling convention.
EL EM EN T IM P L EM EN TAT IO N
Stack-maintenance responsibility Called function pops its own arguments from the stack.
The /Gz compiler option specifies __stdcall for all functions not explicitly declared with a different calling
convention.
For compatibility with previous versions, _stdcall is a synonym for __stdcall unless compiler option /Za
(Disable language extensions) is specified.
Functions declared using the __stdcall modifier return values the same way as functions declared using
__cdecl .
On ARM and x64 processors, __stdcall is accepted and ignored by the compiler; on ARM and x64
architectures, by convention, arguments are passed in registers when possible, and subsequent arguments are
passed on the stack.
For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have
to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention
specified during declaration is assumed at the point of definition. Given this class definition,
struct CMyClass {
void __stdcall mymethod();
};
this
is equivalent to this
Example
In the following example, use of __stdcall results in all WINAPI function types being handled as a standard call:
See also
Argument Passing and Naming Conventions
Keywords
__fastcall
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when
possible. This calling convention only applies to the x86 architecture. The following list shows the
implementation of this calling convention.
EL EM EN T IM P L EM EN TAT IO N
Argument-passing order The first two DWORD or smaller arguments that are found
in the argument list from left to right are passed in ECX and
EDX registers; all other arguments are passed on the stack
from right to left.
Stack-maintenance responsibility Called function pops the arguments from the stack.
NOTE
Future compiler versions may use different registers to store parameters.
Using the /Gr compiler option causes each function in the module to compile as __fastcall unless the function
is declared by using a conflicting attribute, or the name of the function is main .
The __fastcall keyword is accepted and ignored by the compilers that target ARM and x64 architectures; on an
x64 chip, by convention, the first four arguments are passed in registers when possible, and additional
arguments are passed on the stack. For more information, see x64 Calling Convention. On an ARM chip, up to
four integer arguments and eight floating-point arguments may be passed in registers, and additional
arguments are passed on the stack.
For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have
to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention
specified during declaration is assumed at the point of definition. Given this class definition:
struct CMyClass {
void __fastcall mymethod();
};
this:
is equivalent to this:
void __fastcall CMyClass::mymethod() { return; }
For compatibility with previous versions, _fastcall is a synonym for __fastcall unless compiler option /Za
(Disable language extensions) is specified.
Example
In the following example, the function DeleteAggrWrapper is passed arguments in registers:
See also
Argument Passing and Naming Conventions
Keywords
__thiscall
3/6/2021 • 2 minutes to read • Edit Online
The Microsoft-specific __thiscall calling convention is used on C++ class member functions on the x86
architecture. It's the default calling convention used by member functions that don't use variable arguments (
vararg functions).
Under __thiscall , the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed
on the stack from right to left. The this pointer is passed via register ECX, and not on the stack.
On ARM, ARM64, and x64 machines, __thiscall is accepted and ignored by the compiler. That's because they
use a register-based calling convention by default.
One reason to use __thiscall is in classes whose member functions use __clrcall by default. In that case, you
can use __thiscall to make individual member functions callable from native code.
When compiling with /clr:pure , all functions and function pointers are __clrcall unless specified otherwise.
The /clr:pure and /clr:safe compiler options are deprecated in Visual Studio 2015 and unsupported in
Visual Studio 2017.
vararg member functions use the __cdecl calling convention. All function arguments are pushed on the stack,
with the this pointer placed on the stack last.
Because this calling convention applies only to C++, it doesn't have a C name decoration scheme.
When you define a non-static class member function out-of-line, specify the calling convention modifier only in
the declaration. You don't have to specify it again on the out-of-line definition. The compiler uses the calling
convention specified during declaration at the point of definition.
See also
Argument passing and naming conventions
__vectorcall
3/6/2021 • 12 minutes to read • Edit Online
Microsoft Specific
The __vectorcall calling convention specifies that arguments to functions are to be passed in registers, when
possible. __vectorcall uses more registers for arguments than __fastcall or the default x64 calling
convention use. The __vectorcall calling convention is only supported in native code on x86 and x64
processors that include Streaming SIMD Extensions 2 (SSE2) and above. Use __vectorcall to speed functions
that pass several floating-point or SIMD vector arguments and perform operations that take advantage of the
arguments loaded in registers. The following list shows the features that are common to the x86 and x64
implementations of __vectorcall . The differences are explained later in this article.
EL EM EN T IM P L EM EN TAT IO N
C name-decoration convention Function names are suffixed with two "at" signs (@@)
followed by the number of bytes (in decimal) in the
parameter list.
Using the /Gv compiler option causes each function in the module to compile as __vectorcall unless the
function is a member function, is declared with a conflicting calling convention attribute, uses a vararg variable
argument list, or has the name main .
You can pass three kinds of arguments by register in __vectorcall functions: integer type values, vector type
values, and homogeneous vector aggregate (HVA) values.
An integer type satisfies two requirements: it fits in the native register size of the processor—for example, 4
bytes on an x86 machine or 8 bytes on an x64 machine—and it’s convertible to an integer of register length and
back again without changing its bit representation. For example, any type that can be promoted to int on x86 (
long long on x64)—for example, a char or short —or that can be cast to int ( long long on x64) and back
to its original type without change is an integer type. Integer types include pointer, reference, and struct or
union types of 4 bytes (8 bytes on x64) or less. On x64 platforms, larger struct and union types are passed
by reference to memory allocated by the caller; on x86 platforms, they are passed by value on the stack.
A vector type is either a floating-point type—for example, a float or double —or an SIMD vector type—for
example, __m128 or __m256 .
An HVA type is a composite type of up to four data members that have identical vector types. An HVA type has
the same alignment requirement as the vector type of its members. This is an example of an HVA struct
definition that contains three identical vector types and has 32-byte alignment:
typedef struct {
__m256 x;
__m256 y;
__m256 z;
} hva3; // 3 element HVA type on __m256
Declare your functions explicitly with the __vectorcall keyword in header files to allow separately compiled
code to link without errors. Functions must be prototyped to use __vectorcall , and can’t use a vararg variable
length argument list.
A member function may be declared by using the __vectorcall specifier. The hidden this pointer is passed by
register as the first integer type argument.
On ARM machines, __vectorcall is accepted and ignored by the compiler.
For non-static class member functions, if the function is defined out-of-line, the calling convention modifier does
not have to be specified on the out-of-line definition. That is, for class non-static members, the calling
convention specified during declaration is assumed at the point of definition. Given this class definition:
struct MyClass {
void __vectorcall mymethod();
};
this:
is equivalent to this:
The __vectorcall calling convention modifier must be specified when a pointer to a __vectorcall function is
created. The next example creates a typedef for a pointer to a __vectorcall function that takes four double
arguments and returns an __m256 value:
For compatibility with previous versions, _vectorcall is a synonym for __vectorcall unless compiler option
/Za (Disable language extensions) is specified.
// crt_vc64.c
// Build for amd64 with: cl /arch:AVX /W3 /FAs crt_vc64.c
// This example creates an annotated assembly listing in
// crt_vc64.asm.
#include <intrin.h>
#include <xmmintrin.h>
typedef struct {
__m128 array[2];
} hva2; // 2 element HVA type on __m128
typedef struct {
__m256 array[4];
} hva4; // 4 element HVA type on __m256
a = b = d = _mm_set1_ps(3.0f);
c = e = _mm256_set1_ps(5.0f);
h2.array[0] = _mm_set1_ps(6.0f);
h4.array[0] = _mm256_set1_ps(7.0f);
b = example1(a, b, c, d, e);
e = example2(1, b, 3, d, e, 6.0f, 7);
d = example3(1, h2, 3, 4, 5);
f = example4(1, 2.0f, h4, d, 5);
i = example5(1, h2, 3, h4, 5);
h4 = example6(h2, h4, c, h2);
}
// crt_vc86.c
// Build for x86 with: cl /arch:AVX /W3 /FAs crt_vc86.c
// This example creates an annotated assembly listing in
// crt_vc86.asm.
#include <intrin.h>
#include <xmmintrin.h>
typedef struct {
__m128 array[2];
} hva2; // 2 element HVA type on __m128
typedef struct {
__m256 array[4];
} hva4; // 4 element HVA type on __m256
a = b = d = _mm_set1_ps(3.0f);
c = e = _mm256_set1_ps(5.0f);
h2.array[0] = _mm_set1_ps(6.0f);
h4.array[0] = _mm256_set1_ps(7.0f);
b = example1(a, b, c, d, e);
e = example2(1, b, 3, d, e, 6.0f, 7);
d = example3(1, h2, 3, 4, 5);
f = example4(1, 2.0f, h4, d, 5);
i = example5(1, h2, 3, h4, 5);
h4 = example6(h2, h4, c, h2);
}
See also
Argument Passing and Naming Conventions
Keywords
Calling Example: Function Prototype and Call
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The following example shows the results of making a function call using various calling conventions.
This example is based on the following function skeleton. Replace calltype with the appropriate calling
convention.
See also
Calling Conventions
Results of Calling Example
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
__cdecl
The C decorated function name is _MyFunc .
__fastcall
The C decorated name ( __fastcall ) is @MyFunc@20 . The C++ decorated name is implementation-specific.
Microsoft Specific
Functions declared with the naked attribute are emitted without prolog or epilog code, enabling you to write
your own custom prolog/epilog sequences using the inline assembler. Naked functions are provided as an
advanced feature. They enable you to declare a function that is being called from a context other than C/C++,
and thus make different assumptions about where parameters are, or which registers are preserved. Examples
include routines such as interrupt handlers. This feature is particularly useful for writers of virtual device drivers
(VxDs).
See also
Calling Conventions
Rules and Limitations for Naked Functions
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The following rules and limitations apply to naked functions:
The return statement is not permitted.
Structured Exception Handling and C++ Exception Handling constructs are not permitted because they
must unwind across the stack frame.
For the same reason, any form of setjmp is prohibited.
Use of the _alloca function is prohibited.
To ensure that no initialization code for local variables appears before the prolog sequence, initialized
local variables are not permitted at function scope. In particular, the declaration of C++ objects is not
permitted at function scope. There may, however, be initialized data in a nested scope.
Frame pointer optimization (the /Oy compiler option) is not recommended, but it is automatically
suppressed for a naked function.
You cannot declare C++ class objects at the function lexical scope. You can, however, declare objects in a
nested block.
The naked keyword is ignored when compiling with /clr.
For __fastcall naked functions, whenever there is a reference in C/C++ code to one of the register
arguments, the prolog code should store the values of that register into the stack location for that
variable. For example:
// nkdfastcl.cpp
// compile with: /c
// processor: x86
__declspec(naked) int __fastcall power(int i, int j) {
// calculates i^j, assumes that j >= 0
// prolog
__asm {
push ebp
mov ebp, esp
sub esp, __LOCAL_SIZE
// store ECX and EDX into stack locations allocated for i and j
mov i, ecx
mov j, edx
}
{
int k = 1; // return value
while (j-- > 0)
k *= i;
__asm {
mov eax, k
};
}
// epilog
__asm {
mov esp, ebp
pop ebp
ret
}
}
See also
Naked Function Calls
Considerations for Writing Prolog/Epilog Code
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Before writing your own prolog and epilog code sequences, it is important to understand how the stack frame is
laid out. It is also useful to know how to use the __LOCAL_SIZE symbol.
The localbytes variable represents the number of bytes needed on the stack for local variables, and the
<registers> variable is a placeholder that represents the list of registers to be saved on the stack. After pushing
the registers, you can place any other appropriate data on the stack. The following is the corresponding epilog
code:
The stack always grows down (from high to low memory addresses). The base pointer ( ebp ) points to the
pushed value of ebp . The locals area begins at ebp-4 . To access local variables, calculate an offset from ebp by
subtracting the appropriate value from ebp .
__LOCAL_SIZE
The compiler provides a symbol, __LOCAL_SIZE , for use in the inline assembler block of function prolog code.
This symbol is used to allocate space for local variables on the stack frame in custom prolog code.
The compiler determines the value of __LOCAL_SIZE . Its value is the total number of bytes of all user-defined
local variables and compiler-generated temporary variables. __LOCAL_SIZE can be used only as an immediate
operand; it cannot be used in an expression. You must not change or redefine the value of this symbol. For
example:
The following example of a naked function containing custom prolog and epilog sequences uses the
__LOCAL_SIZE symbol in the prolog sequence:
// the__local_size_symbol.cpp
// processor: x86
__declspec ( naked ) int main() {
int i;
int j;
__asm { /* prolog */
push ebp
mov ebp, esp
sub esp, __LOCAL_SIZE
}
/* Function body */
__asm { /* epilog */
mov esp, ebp
pop ebp
ret
}
}
See also
Naked Function Calls
Floating Point Coprocessor and Calling Conventions
3/6/2021 • 2 minutes to read • Edit Online
If you are writing assembly routines for the floating point coprocessor, you must preserve the floating point
control word and clean the coprocessor stack unless you are returning a float or double value (which your
function should return in ST(0)).
See also
Calling Conventions
Obsolete Calling Conventions
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __pascal , __for tran , and __syscall calling conventions are no longer supported. You can emulate their
functionality by using one of the supported calling conventions and appropriate linker options.
<windows.h> now supports the WINAPI macro, which translates to the appropriate calling convention for the
target. Use WINAPI where you previously used PASCAL or __far __pascal .
END Microsoft Specific
See also
Argument Passing and Naming Conventions
restrict (C++ AMP)
3/6/2021 • 2 minutes to read • Edit Online
The restriction specifier can be applied to function and lambda declarations. It enforces restrictions on the code
in the function and on the behavior of the function in applications that use the C++ Accelerated Massive
Parallelism (C++ AMP) runtime.
NOTE
For information about the restrict keyword that is part of the __declspec storage-class attributes, see restrict.
restrict(cpu) The function can use the full C++ language. Only other
functions that are declared by using restrict(cpu) functions
can call the function.
restrict(amp) The function can only use the subset of the C++ language
that C++ AMP can accelerate.
A sequence of restrict(cpu) and restrict(amp) . The function must adhere to the limitations of both
restrict(cpu) and restrict(amp) . The function can be
called by functions that are declared by using
restrict(cpu) , restrict(amp) , restrict(cpu, amp) ,
or restrict(amp, cpu) .
Remarks
The restrict keyword is a contextual keyword. The restriction specifiers, cpu and amp are not reserved
words. The list of specifiers is not extensible. A function that does not have a restrict clause is the same as a
function that has the restrict(cpu) clause.
A function that has the restrict(amp) clause has the following limitations:
The function can call only functions that have the restrict(amp) clause.
The function must be inlinable.
The function can declare only int , unsigned int , float , and double variables, and classes and
structures that contain only these types. bool is also allowed, but it must be 4-byte-aligned if you use it
in a compound type.
Lambda functions cannot capture by reference and cannot capture pointers.
References and single-indirection pointers are supported only as local variables, function arguments, and
return types.
The following are not allowed:
Recursion.
Variables declared with the volatile keyword.
Virtual functions.
Pointers to functions.
Pointers to member functions.
Pointers in structures.
Pointers to pointers.
goto statements.
Labeled statements.
try , catch , or throw statements.
Global variables.
Static variables. Use tile_static Keyword instead.
dynamic_cast casts.
The typeid operator.
asm declarations.
Varargs.
For a discussion of function limitations, see restrict(amp) restrictions.
Example
The following example shows how to use the restrict(amp) clause.
See also
C++ AMP (C++ Accelerated Massive Parallelism)
tile_static Keyword
3/6/2021 • 3 minutes to read • Edit Online
The tile_static keyword is used to declare a variable that can be accessed by all threads in a tile of threads. The
lifetime of the variable starts when execution reaches the point of declaration and ends when the kernel function
returns. For more information on using tiles, see Using Tiles.
The tile_static keyword has the following limitations:
It can be used only on variables that are in a function that has the restrict(amp) modifier.
It cannot be used on variables that are pointer or reference types.
A tile_static variable cannot have an initializer. Default constructors and destructors are not invoked
automatically.
The value of an uninitialized tile_static variable is undefined.
If a tile_static variable is declared in a call graph that is rooted by a non-tiled call to parallel_for_each ,
a warning is generated and the behavior of the variable is undefined.
Example
The following example shows how a tile_static variable can be used to accumulate data across several threads
in a tile.
// Sample data:
int sampledata[] = {
2, 2, 9, 7, 1, 4,
4, 4, 8, 8, 3, 4,
1, 5, 1, 2, 5, 2,
6, 8, 3, 2, 7, 2};
// The tiles:
// 2 2 9 7 1 4
// 4 4 8 8 3 4
//
// 1 5 1 2 5 2
// 6 8 3 2 7 2
// Averages:
int averagedata[] = {
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
};
parallel_for_each(
// Create threads for sample.extent and divide the extent into 2 x 2 tiles.
sample.extent.tile<2,2>(),
[=](tiled_index<2,2> idx) restrict(amp)
{
// Create a 2 x 2 array to hold the values in this tile.
tile_static int nums[2][2];
// Copy the values for the tile into the 2 x 2 array.
nums[idx.local[1]][idx.local[0]] = sample[idx.global];
nums[idx.local[1]][idx.local[0]] = sample[idx.global];
// When all the threads have executed and the 2 x 2 array is complete, find the average.
idx.barrier.wait();
int sum = nums[0][0] + nums[0][1] + nums[1][0] + nums[1][1];
// Copy the average into the array_view.
average[idx.global] = sum / 4;
}
);
// Output:
// 3 3 8 8 3 3
// 3 3 8 8 3 3
// 5 5 2 2 4 4
// 5 5 2 2 4 4
// Sample data.
int sampledata[] = {
2, 2, 9, 7, 1, 4,
4, 4, 8, 8, 3, 4,
1, 5, 1, 2, 5, 2,
6, 8, 3, 2, 7, 2};
// Averages.
int averagedata[] = {
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
};
parallel_for_each(
// Create threads for sample.grid and divide the grid into 2 x 2 tiles.
sample.extent.tile<2,2>(),
[=](tiled_index<2,2> idx) restrict(amp)
{
// Create a 2 x 2 array to hold the values in this tile.
tile_static int nums[2][2];
// Copy the values for the tile into the 2 x 2 array.
nums[idx.local[1]][idx.local[0]] = sample[idx.global];
// When all the threads have executed and the 2 x 2 array is complete, find the average.
idx.barrier.wait();
int sum = nums[0][0] + nums[0][1] + nums[1][0] + nums[1][1];
// Copy the average into the array_view.
average[idx.global] = sum / 4;
}
);
See also
Microsoft-Specific Modifiers
C++ AMP Overview
parallel_for_each Function (C++ AMP)
Walkthrough: Matrix Multiplication
__declspec
3/8/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which
specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute listed
below. Examples of other storage-class modifiers include the static and extern keywords. However, these
keywords are part of the ANSI specification of the C and C++ languages, and as such are not covered by
extended attribute syntax. The extended attribute syntax simplifies and standardizes Microsoft-specific
extensions to the C and C++ languages.
Grammar
decl-specifier :
__declspec ( extended-decl-modifier-seq )
extended-decl-modifier-seq :
extended-decl-modifier opt
extended-decl-modifier extended-decl-modifier-seq
extended-decl-modifier :
align( number )
allocate(" segname ")
allocator
appdomain
code_seg(" segname ")
deprecated
dllimport
dllexport
jitintrinsic
naked
noalias
noinline
noreturn
nothrow
novtable
no_sanitize_address
process
property( { get= get-func-name | ,put= put-func-name } )
restrict
safebuffers
selectany
spectre(nomitigation)
thread
uuid(" ComObjectGUID ")
White space separates the declaration modifier sequence. Examples appear in later sections.
Extended attribute grammar supports these Microsoft-specific storage-class attributes: align , allocate ,
allocator , appdomain , code_seg , deprecated , dllexport , dllimport , jitintrinsic , naked , noalias ,
noinline , noreturn , nothrow , novtable , no_sanitize_address , process , restrict , safebuffers , selectany ,
spectre , and thread . It also supports these COM-object attributes: property and uuid .
For compatibility with previous versions, _declspec is a synonym for __declspec unless compiler option /Za
(Disable language extensions) is specified.
The __declspec keywords should be placed at the beginning of a simple declaration. The compiler ignores,
without warning, any __declspec keywords placed after * or & and in front of the variable identifier in a
declaration.
A __declspec attribute specified in the beginning of a user-defined type declaration applies to the variable of
that type. For example:
In this case, the attribute applies to varX . A __declspec attribute placed after the class or struct keyword
applies to the user-defined type. For example:
__declspec(selectany) int * pi1 = 0; //Recommended, selectany & int both part of decl-specifier
int __declspec(selectany) * pi2 = 0; //OK, selectany & int both part of decl-specifier
int * __declspec(selectany) pi3 = 0; //ERROR, selectany is not part of a declarator
The following code declares an integer thread local variable and initializes it with a value:
See also
Keywords
C Extended Storage-Class Attributes
align (C++)
3/6/2021 • 7 minutes to read • Edit Online
In Visual Studio 2015 and later, use the C++11 standard alignas specifier to control alignment. For more
information, see Alignment.
Microsoft Specific
Use __declspec(align(#)) to precisely control the alignment of user-defined data (for example, static allocations
or automatic data in a function).
Syntax
__declspec( align( # ) ) declarator
Remarks
Writing applications that use the latest processor instructions introduces some new constraints and issues.
Many new instructions require data that's aligned to 16-byte boundaries. Additionally, by aligning frequently
used data to the processor's cache line size, you improve cache performance. For example, if you define a
structure whose size is less than 32 bytes, you may want 32 byte alignment to make sure that objects of that
structure type are efficiently cached.
# is the alignment value. Valid entries are integer powers of two from 1 to 8192 (bytes), such as 2, 4, 8, 16, 32, or
64. declarator is the data that you're declaring as aligned.
For information about how to return a value of type size_t that is the alignment requirement of the type, see
alignof . For information about how to declare unaligned pointers when targeting 64-bit processors, see
__unaligned .
You can use __declspec(align(#)) when you define a struct , union , or class , or when you declare a variable.
The compiler doesn't guarantee or attempt to preserve the alignment attribute of data during a copy or data
transform operation. For example, memcpy can copy a struct declared with __declspec(align(#)) to any location.
Ordinary allocators (for example, malloc , C++ operator new , and the Win32 allocators) typically return
memory that isn't sufficiently aligned for __declspec(align(#)) structures or arrays of structures. To guarantee
that the destination of a copy or data transformation operation is correctly aligned, use _aligned_malloc . Or,
write your own allocator.
You can't specify alignment for function parameters. When you pass data that has an alignment attribute by
value on the stack, its alignment is controlled by the calling convention. If data alignment is important in the
called function, copy the parameter into correctly aligned memory before use.
Without __declspec(align(#)) , the compiler generally aligns data on natural boundaries based on the target
processor and the size of the data, up to 4-byte boundaries on 32-bit processors, and 8-byte boundaries on 64-
bit processors. Data in classes or structures is aligned in the class or structure at the minimum of its natural
alignment and the current packing setting (from #pragma pack or the /Zp compiler option).
This example demonstrates the use of __declspec(align(#)) :
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
This type now has a 32-byte alignment attribute. It means that all static and automatic instances start on a 32-
byte boundary. Additional structure types declared with this type as a member preserve this type's alignment
attribute, that is, any structure with Str1 as an element has an alignment attribute of at least 32.
Here, sizeof(struct Str1) is equal to 32. It implies that if an array of Str1 objects is created, and the base of
the array is 32-byte aligned, each member of the array is also 32-byte aligned. To create an array whose base is
correctly aligned in dynamic memory, use _aligned_malloc . Or, write your own allocator.
The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the
nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is
larger.
The compiler uses these rules for structure alignment:
Unless overridden with __declspec(align(#)) , the alignment of a scalar structure member is the
minimum of its size and the current packing.
Unless overridden with __declspec(align(#)) , the alignment of a structure is the maximum of the
individual alignments of its member(s).
A structure member is placed at an offset from the start of its parent structure that's the smallest multiple
of its alignment greater than or equal to the offset of the end of the previous member.
The size of a structure is the smallest multiple of its alignment greater than or equal to the offset of the
end of its last member.
__declspec(align(#)) can only increase alignment restrictions.
For more information, see:
align Examples
Defining New Types with __declspec(align(#))
align Examples
The following examples show how __declspec(align(#)) affects the size and alignment of data structures. The
examples assume the following definitions:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
In this example, the S1 structure is defined by using __declspec(align(32)) . All uses of S1 for a variable
definition or in other type declarations are 32-byte aligned. sizeof(struct S1) returns 32, and S1 has 16
padding bytes following the 16 bytes required to hold the four integers. Each int member requires 4-byte
alignment, but the alignment of the structure itself is declared to be 32. Then the overall alignment is 32.
struct CACHE_ALIGN S1 { // cache align all instances of S1
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned
In this example, sizeof(struct S2) returns 16, which is exactly the sum of the member sizes, because that is a
multiple of the largest alignment requirement (a multiple of 8).
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
struct S3 {
struct S1 s1; // S3 inherits cache alignment requirement
// from S1 declaration
int a; // a is now cache aligned because of s1
// 28 bytes of trailing padding
};
In this example, notice that a has the alignment of its natural type, in this case, 4 bytes. However, S1 must be
32-byte aligned. 28 bytes of padding follow a , so that s1 starts at offset 32. S4 then inherits the alignment
requirement of S1 , because it's the largest alignment requirement in the structure. sizeof(struct S4) returns
64.
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
The following three variable declarations also use __declspec(align(#)) . In each case, the variable must be 32-
byte aligned. In the array, the base address of the array, not each array member, is 32-byte aligned. The sizeof
value for each array member is unaffected when you use __declspec(align(#)) .
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
In this example, notice that aligning the structure itself and aligning the first element have the same effect:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
void fn() {
int a;
char b;
long c;
char d[10]
}
The alignment when memory is allocated on the heap depends on which allocation function is called. For
example, if you use malloc , the result depends on the operand size. If arg >= 8, the memory returned is 8 byte
aligned. If arg < 8, the alignment of the memory returned is the first power of 2 less than arg. For example, if
you use malloc(7) , the alignment is 4 bytes.
Now, aType and bType are the same size (8 bytes) but variables of type bType are 32-byte aligned.
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
The following table lists the offset of each member under different /Zp (or #pragma pack ) values, showing how
the two interact.
a 0 0 0 0
b 1 2 2 2
c 3 4 4 8
d 32 32 32 32
e 40 40 40 40
f 41 42 44 48
sizeof(S) 64 64 64 64
Microsoft Specific
The allocate declaration specifier names a data segment in which the data item will be allocated.
Syntax
__declspec(allocate(" segname )) declarator
Remarks
The name segname must be declared using one of the following pragmas:
code_seg
const_seg
data_seg
init_seg
section
Example
// allocate.cpp
#pragma section("mycode", read)
__declspec(allocate("mycode")) int i = 0;
int main() {
}
See also
__declspec
Keywords
allocator
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The allocator declaration specifier can be applied to custom memory-allocation functions to make the
allocations visible via Event Tracing for Windows (ETW).
Syntax
__declspec(allocator)
Remarks
The native memory profiler in Visual Studio works by collecting allocation ETW event data emitted by during
runtime. Allocators in the CRT and Windows SDK have been annotated at the source level so that their allocation
data can be captured. If you are writing your own allocators, then any functions that return a pointer to newly
allocated heap memory can be decorated with __declspec(allocator) , as seen in this example for myMalloc:
For more information, see Measure memory usage in Visual Studio and Custom native ETW heap events.
END Microsoft Specific
appdomain
3/6/2021 • 2 minutes to read • Edit Online
Specifies that each application domain of your managed application should have its own copy of a particular
global variable or static member variable. See Application Domains and Visual C++ for more information.
Every application domain has its own copy of a per-appdomain variable. A constructor of an appdomain
variable is executed when an assembly is loaded into an application domain, and the destructor is executed
when the application domain is unloaded.
If you want all application domains within a process in the common language runtime to share a global variable,
use the __declspec(process) modifier. __declspec(process) is in effect by default under /clr. The /clr :pure and
/clr :safe compiler options are deprecated in Visual Studio 2015 and unsupported in Visual Studio 2017.
__declspec(appdomain) is only valid when one of the /clr compiler options is used. Only a global variable, static
member variable, or a static local variable can be marked with __declspec(appdomain) . It is an error to apply
__declspec(appdomain) to static members of managed types because they always have this behavior.
Using __declspec(appdomain) is similar to using Thread Local Storage (TLS). Threads have their own storage, as
do application domains. Using __declspec(appdomain) ensures the global variable has its own storage in each
application domain created for this application.
There are limitations to mixing the use of per process and per appdomain variables; see process for more
information.
For example, at program start up, all per-process variables are initialized, then all per-appdomain variables are
initialized. Therefore when a per-process variable is being initialized, it cannot depend on the value of any per-
application domain variable. It is bad practice to mix the use (assignment) of per appdomain and per process
variables.
For information on how to call a function in a specific application domain, see call_in_appdomain Function.
Example
// declspec_appdomain.cpp
// compile with: /clr
#include <stdio.h>
using namespace System;
class CGlobal {
public:
CGlobal(bool bProcess) {
Counter = 10;
m_bProcess = bProcess;
Console::WriteLine("__declspec({0}) CGlobal::CGlobal constructor", m_bProcess ? (String^)"process" :
(String^)"appdomain");
}
~CGlobal() {
Console::WriteLine("__declspec({0}) CGlobal::~CGlobal destructor", m_bProcess ? (String^)"process" :
(String^)"appdomain");
}
int Counter;
private:
bool m_bProcess;
bool m_bProcess;
};
int main() {
AppDomain^ defaultDomain = AppDomain::CurrentDomain;
AppDomain^ domain = AppDomain::CreateDomain("Domain 1");
AppDomain^ domain2 = AppDomain::CreateDomain("Domain 2");
CrossAppDomainDelegate^ changeDelegate = gcnew CrossAppDomainDelegate(&Functions::change);
CrossAppDomainDelegate^ displayDelegate = gcnew CrossAppDomainDelegate(&Functions::display);
AppDomain::Unload(domain);
AppDomain::Unload(domain2);
}
__declspec(process) CGlobal::CGlobal constructor
__declspec(appdomain) CGlobal::CGlobal constructor
Initial value
process_global value in appdomain 'declspec_appdomain.exe': 10
appdomain_global value in appdomain 'declspec_appdomain.exe': 10
__declspec(appdomain) CGlobal::CGlobal constructor
process_global value in appdomain 'Domain 1': 10
appdomain_global value in appdomain 'Domain 1': 10
__declspec(appdomain) CGlobal::CGlobal constructor
process_global value in appdomain 'Domain 2': 10
appdomain_global value in appdomain 'Domain 2': 10
Changed value
process_global value in appdomain 'declspec_appdomain.exe': 20
appdomain_global value in appdomain 'declspec_appdomain.exe': 10
process_global value in appdomain 'Domain 1': 20
appdomain_global value in appdomain 'Domain 1': 11
process_global value in appdomain 'Domain 2': 20
appdomain_global value in appdomain 'Domain 2': 12
__declspec(appdomain) CGlobal::~CGlobal destructor
__declspec(appdomain) CGlobal::~CGlobal destructor
__declspec(appdomain) CGlobal::~CGlobal destructor
__declspec(process) CGlobal::~CGlobal destructor
See also
__declspec
Keywords
code_seg (__declspec)
3/6/2021 • 3 minutes to read • Edit Online
Microsoft Specific
The code_seg declaration attribute names an executable text segment in the .obj file in which the object code
for the function or class member functions will be stored.
Syntax
__declspec(code_seg("segname")) declarator
Remarks
The __declspec(code_seg(...)) attribute enables the placement of code into separate named segments that can
be paged or locked in memory individually. You can use this attribute to control the placement of instantiated
templates and compiler-generated code.
A segment is a named block of data in an .obj file that is loaded into memory as a unit. A text segment is a
segment that contains executable code. The term section is often used interchangeably with segment.
Object code that's generated when declarator is defined is put in the text segment specified by segname , which
is a narrow-string literal. The name segname does not have to be specified in a section pragma before it can be
used in a declaration. By default, when no code_seg is specified, object code is put in a segment named .text. A
code_seg attribute overrides any existing #pragma code_seg directive. A code_seg attribute applied to a
member function overrides any code_seg attribute applied to the enclosing class.
If an entity has a code_seg attribute, all declarations and definitions of the same entity must have identical
code_seg attributes. If a base-class has a code_seg attribute, derived classes must have the same attribute.
When a code_seg attribute is applied to a namespace-scope function or a member function, the object code for
that function is put in the specified text segment. When this attribute is applied to a class, all member functions
of the class and nested classes—this includes compiler-generated special member functions—are put in the
specified segment. Locally defined classes—for example, classes defined in a member function body—do not
inherit the code_seg attribute of the enclosing scope.
When a code_seg attribute is applied to a template class or template function, all implicit specializations of the
template are put in the specified segment. Explicit or partial specializations do not inherit the code_seg
attribute from the primary template. You may specify the same or a different code_seg attribute on the
specialization. A code_seg attribute can’t be applied to an explicit template instantiation.
By default, compiler-generated code such as a special member function is put in the .text segment. The
#pragma code_seg directive does not override this default. Use the code_seg attribute on the class, class
template, or function template to control where compiler-generated code is put.
Lambdas inherit code_seg attributes from their enclosing scope. To specify a segment for a lambda, apply a
code_seg attribute after the parameter-declaration clause and before any mutable or exception specification,
any trailing return-type specification, and the lambda body. For more information, see Lambda Expression
Syntax. This example defines a lambda in a segment named PagedMem:
auto Sqr = [](int t) __declspec(code_seg("PagedMem")) -> int { return t*t; };
Be careful when you put specific member functions—especially virtual member functions—in different
segments. If you define a virtual function in a derived class that resides in a paged segment when the base class
method resides in a non-paged segment, other base class methods or user code may assume that invoking the
virtual method will not trigger a page fault.
Example
This example shows how a code_seg attribute controls segment placement when implicit and explicit template
specialization is used:
// code_seg.cpp
// Compile: cl /EHsc /W4 code_seg.cpp
int main()
{
// implicit double specialization uses base template's
// __declspec(code_seg("Segment_1")) to place object code
Example<double> doubleExample{};
doubleExample.VirtualMemberFunction(3.14L);
This topic is about the Microsoft-specific deprecated declspec declaration. For information about the C++14
[[deprecated]] attribute, and guidance on when to use that attribute vs. the Microsoft-specific declspec or
pragma, see C++ Standard Attributes.
With the exceptions noted below, the deprecated declaration offers the same functionality as the deprecated
pragma:
The deprecated declaration lets you specify particular forms of function overloads as deprecated,
whereas the pragma form applies to all overloaded forms of a function name.
The deprecated declaration lets you specify a message that will display at compile time. The text of the
message can be from a macro.
Macros can only be marked as deprecated with the deprecated pragma.
If the compiler encounters the use of a deprecated identifier or the standard [[deprecated]] attribute, a C4996
warning is thrown.
Examples
The following sample shows how to mark functions as deprecated, and how to specify a message that will be
displayed at compile time, when the deprecated function is used.
// deprecated.cpp
// compile with: /W3
#define MY_TEXT "function is deprecated"
void func1(void) {}
__declspec(deprecated) void func1(int) {}
__declspec(deprecated("** this is a deprecated function **")) void func2(int) {}
__declspec(deprecated(MY_TEXT)) void func3(int) {}
int main() {
func1();
func1(1); // C4996
func2(1); // C4996
func3(1); // C4996
}
The following sample shows how to mark classes as deprecated, and how to specify a message that will be
displayed at compile time, when the deprecated class is used.
// deprecate_class.cpp
// compile with: /W3
struct __declspec(deprecated) X {
void f(){}
};
int main() {
X x; // C4996
X2 x2; // C4996
}
See also
__declspec
Keywords
dllexport, dllimport
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The dllexport and dllimport storage-class attributes are Microsoft-specific extensions to the C and C++
languages. You can use them to export and import functions, data, and objects to or from a DLL.
Syntax
__declspec( dllimport ) declarator
__declspec( dllexport ) declarator
Remarks
These attributes explicitly define the DLL's interface to its client, which can be the executable file or another DLL.
Declaring functions as dllexport eliminates the need for a module-definition (.def) file, at least with respect to
the specification of exported functions. The dllexport attribute replaces the __expor t keyword.
If a class is marked declspec(dllexport), any specializations of class templates in the class hierarchy are implicitly
marked as declspec(dllexport). This means that class templates are explicitly instantiated and the class's
members must be defined.
dllexport of a function exposes the function with its decorated name. For C++ functions, this includes name
mangling. For C functions or functions that are declared as extern "C" , this includes platform-specific
decoration that's based on the calling convention. For information on name decoration in C/C++ code, see
Decorated Names. No name decoration is applied to exported C functions or C++ extern "C" functions using
the __cdecl calling convention.
To export an undecorated name, you can link by using a Module Definition (.def) file that defines the
undecorated name in an EXPORTS section. For more information, see EXPORTS. Another way to export an
undecorated name is to use a #pragma comment(linker, "/export:alias=decorated_name") directive in the source
code.
When you declare dllexport or dllimport , you must use extended attribute syntax and the __declspec
keyword.
Example
// Example of the dllimport and dllexport class attributes
__declspec( dllimport ) int i;
__declspec( dllexport ) void func();
Alternatively, to make your code more readable, you can use macro definitions:
#define DllImport __declspec( dllimport )
#define DllExport __declspec( dllexport )
See also
__declspec
Keywords
Definitions and Declarations (C++)
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The DLL interface refers to all items (functions and data) that are known to be exported by some program in the
system; that is, all items that are declared as dllimport or dllexport . All declarations included in the DLL
interface must specify either the dllimport or dllexport attribute. However, the definition must specify only
the dllexport attribute. For example, the following function definition generates a compiler error:
The use of dllexport implies a definition, while dllimport implies a declaration. You must use the extern
keyword with dllexport to force a declaration; otherwise, a definition is implied. Thus, the following examples
are correct:
void func() {
static __declspec( dllimport ) int s; // Error; not declared
// extern.
__declspec( dllimport ) int m; // Okay; this is a
// declaration.
__declspec( dllexport ) int n; // Error; implies external
// definition in local scope.
extern __declspec( dllimport ) int i; // Okay; this is a
// declaration.
extern __declspec( dllexport ) int k; // Okay; extern implies
// declaration.
__declspec( dllexport ) int x = 5; // Error; implies external
// definition in local scope.
}
END Microsoft Specific
See also
dllexport, dllimport
Defining Inline C++ Functions with dllexport and
dllimport
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
You can define as inline a function with the dllexport attribute. In this case, the function is always instantiated
and exported, whether or not any module in the program references the function. The function is presumed to
be imported by another program.
You can also define as inline a function declared with the dllimport attribute. In this case, the function can be
expanded (subject to /Ob specifications), but never instantiated. In particular, if the address of an inline imported
function is taken, the address of the function residing in the DLL is returned. This behavior is the same as taking
the address of a non-inline imported function.
These rules apply to inline functions whose definitions appear within a class definition. In addition, static local
data and strings in inline functions maintain the same identities between the DLL and client as they would in a
single program (that is, an executable file without a DLL interface).
Exercise care when providing imported inline functions. For example, if you update the DLL, don't assume that
the client will use the changed version of the DLL. To ensure that you are loading the proper version of the DLL,
rebuild the DLL's client as well.
END Microsoft Specific
See also
dllexport, dllimport
General Rules and Limitations
3/6/2021 • 3 minutes to read • Edit Online
Microsoft Specific
If you declare a function or object without the dllimport or dllexport attribute, the function or object is
not considered part of the DLL interface. Therefore, the definition of the function or object must be
present in that module or in another module of the same program. To make the function or object part of
the DLL interface, you must declare the definition of the function or object in the other module as
dllexport . Otherwise, a linker error is generated.
If you declare a function or object with the dllexport attribute, its definition must appear in some
module of the same program. Otherwise, a linker error is generated.
If a single module in your program contains both dllimport and dllexport declarations for the same
function or object, the dllexport attribute takes precedence over the dllimport attribute. However, a
compiler warning is generated. For example:
In C++, you can initialize a globally declared or static local data pointer or with the address of a data
object declared with the dllimport attribute, which generates an error in C. In addition, you can initialize
a static local function pointer with the address of a function declared with the dllimport attribute. In C,
such an assignment sets the pointer to the address of the DLL import thunk (a code stub that transfers
control to the function) rather than the address of the function. In C++, it sets the pointer to the address
of the function. For example:
void func2()
{
static int *pi = &i; // Error in C
static void ( *pf )( void ) = &func1; // Address of thunk in C,
// function in C++
}
However, because a program that includes the dllexport attribute in the declaration of an object must
provide the definition for that object somewhere in the program, you can initialize a global or local static
function pointer with the address of a dllexport function. Similarly, you can initialize a global or local
static data pointer with the address of a dllexport data object. For example, the following code does not
generate errors in C or C++:
__declspec( dllexport ) void func1( void );
__declspec( dllexport ) int i;
void func2()
{
static int *pi = &i; // Okay
static void ( *pf )( void ) = &func1; // Okay
}
If you apply dllexport to a regular class that has a base class that is not marked as dllexport , the
compiler will generate C4275.
The compiler generates the same warning if the base class is a specialization of a class template. To work
around this, mark the base-class with dllexport . The problem with a specialization of a class template is
where to place the __declspec(dllexport) ; you are not allowed to mark the class template. Instead,
explicitly instantiate the class template and mark this explicit instantiation with dllexport . For example:
This workaround fails if the template argument is the deriving class. For example:
Because this is common pattern with templates, the compiler changed the semantics of dllexport when
it is applied to a class that has one or more base-classes and when one or more of the base classes is a
specialization of a class template. In this case, the compiler implicitly applies dllexport to the
specializations of class templates. You can do the following and not get a warning:
See also
dllexport, dllimport
Using dllimport and dllexport in C++ Classes
3/6/2021 • 3 minutes to read • Edit Online
Microsoft Specific
You can declare C++ classes with the dllimport or dllexport attribute. These forms imply that the entire class
is imported or exported. Classes exported this way are called exportable classes.
The following example defines an exportable class. All its member functions and static data are exported:
class DllExport C {
int i;
virtual int func( void ) { return 1; }
};
Note that explicit use of the dllimport and dllexport attributes on members of an exportable class is
prohibited.
dllexport Classes
When you declare a class dllexport , all its member functions and static data members are exported. You must
provide the definitions of all such members in the same program. Otherwise, a linker error is generated. The
one exception to this rule applies to pure virtual functions, for which you need not provide explicit definitions.
However, because a destructor for an abstract class is always called by the destructor for the base class, pure
virtual destructors must always provide a definition. Note that these rules are the same for nonexportable
classes.
If you export data of class type or functions that return classes, be sure to export the class.
dllimport Classes
When you declare a class dllimport , all its member functions and static data members are imported. Unlike the
behavior of dllimport and dllexport on nonclass types, static data members cannot specify a definition in the
same program in which a dllimport class is defined.
See also
dllexport, dllimport
jitintrinsic
3/6/2021 • 2 minutes to read • Edit Online
Marks the function as significant to the 64-bit common language runtime. This is used on certain functions in
Microsoft-provided libraries.
Syntax
__declspec(jitintrinsic)
Remarks
jitintrinsic adds a MODOPT (IsJitIntrinsic) to a function signature.
Users are discouraged from using this __declspec modifier, as unexpected results can occur.
See also
__declspec
Keywords
naked (C++)
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
For functions declared with the naked attribute, the compiler generates code without prolog and epilog code.
You can use this feature to write your own prolog/epilog code sequences using inline assembler code. Naked
functions are particularly useful in writing virtual device drivers. Note that the naked attribute is only valid on
x86 and ARM, and is not available on x64.
Syntax
__declspec(naked) declarator
Remarks
Because the naked attribute is only relevant to the definition of a function and is not a type modifier, naked
functions must use extended attribute syntax and the __declspec keyword.
The compiler cannot generate an inline function for a function marked with the naked attribute, even if the
function is also marked with the __forceinline keyword.
The compiler issues an error if the naked attribute is applied to anything other than the definition of a non-
member method.
Examples
This code defines a function with the naked attribute:
Or, alternately:
The naked attribute affects only the nature of the compiler's code generation for the function's prolog and
epilog sequences. It does not affect the code that is generated for calling such functions. Thus, the naked
attribute is not considered part of the function's type, and function pointers cannot have the naked attribute.
Furthermore, the naked attribute cannot be applied to a data definition. For example, this code sample
generates an error:
The naked attribute is relevant only to the definition of the function and cannot be specified in the function's
prototype. For example, this declaration generates a compiler error:
__declspec( naked ) int func(); // Error--naked attribute not permitted on function declarations
See also
__declspec
Keywords
Naked Function Calls
noalias
3/6/2021 • 2 minutes to read • Edit Online
Microsoft-specific
noalias means that a function call doesn't modify or reference visible global state and only modifies the
memory pointed to directly by pointer parameters (first-level indirections).
If a function is annotated as noalias , the optimizer can assume that only the parameters themselves, and only
first-level indirections of pointer parameters, are referenced or modified inside the function.
The noaliasannotation only applies within the body of the annotated function. Marking a function as
__declspec(noalias) doesn't affect the aliasing of pointers returned by the function.
Example
The following sample demonstrates the use of __declspec(noalias) .
When the function multiply that accesses memory is annotated __declspec(noalias) , it tells the compiler that
this function doesn't modify the global state except through the pointers in its parameter list.
// declspec_noalias.c
#include <stdio.h>
#include <stdlib.h>
#define M 800
#define N 600
#define P 700
a = ma(m * n);
if (!a) exit(1);
for (i=0; i<m; i++)
for (j=0; j<n; j++)
a[i*n+j] = 0.1/k++;
return a;
}
int main()
{
float * a, * b, * c;
if (!mempool)
{
puts("ERROR: Malloc returned null");
exit(1);
}
memptr = mempool;
a = init(M, N);
b = init(N, P);
c = init(M, P);
multiply(a, b, c);
}
See also
__declspec
Keywords
__declspec(restrict)
noinline
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
__declspec(noinline) tells the compiler to never inline a particular member function (function in a class).
It may be worthwhile to not inline a function if it is small and not critical to the performance of your code. That
is, if the function is small and not likely to be called often, such as a function that handles an error condition.
Keep in mind that if a function is marked noinline , the calling function will be smaller and thus, itself a
candidate for compiler inlining.
class X {
__declspec(noinline) int mbrfunc() {
return 0;
} // will not inline
};
See also
__declspec
Keywords
inline, __inline, __forceinline
noreturn
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
This __declspec attribute tells the compiler that a function does not return. As a consequence, the compiler
knows that the code following a call to a __declspec(noreturn) function is unreachable.
If the compiler finds a function with a control path that does not return a value, it generates a warning (C4715)
or error message (C2202). If the control path cannot be reached due to a function that never returns, you can
use __declspec(noreturn) to prevent this warning or error.
NOTE
Adding __declspec(noreturn) to a function that is expected to return can result in undefined behavior.
Example
In the following sample,the else clause does not contain a return statement. Declaring fatal as
__declspec(noreturn) avoids an error or warning message.
// noreturn2.cpp
__declspec(noreturn) extern void fatal () {}
int main() {
if(1)
return 1;
else if(0)
return 0;
else
fatal();
}
See also
__declspec
Keywords
no_sanitize_address
3/8/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The __declspec(no_sanitize_address) specifier tells the compiler to disable the address sanitizer on functions,
local variables, or global variables. This specifier is used in conjunction with AddressSanitizer.
NOTE
__declspec(no_sanitize_address) disables compiler behavior, not runtime behavior.
Example
See the AddressSanitizer build reference for examples.
END Microsoft Specific
See also
__declspec
Keywords
AddressSanitizer
nothrow (C++)
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
A __declspec extended attribute which can be used in the declaration of functions.
Syntax
return-type __declspec(nothrow) [call-convention] function-name ([argument-list])
Remarks
We recommend that all new code use the noexcept operator rather than __declspec(nothrow) .
This attribute tells the compiler that the declared function and the functions it calls never throw an exception.
However, it does not enforce the directive. In other words, it never causes std::terminate to be invoked, unlike
noexcept , or in std:c++17 mode (Visual Studio 2017 version 15.5 and later), throw() .
With the synchronous exception handling model, now the default, the compiler can eliminate the mechanics of
tracking the lifetime of certain unwindable objects in such a function, and significantly reduce the code size.
Given the following preprocessor directive, the three function declarations below are equivalent in /std:c++14
mode:
In /std:c++17 mode, throw() is not equivalent to the others that use __declspec(nothrow) because it causes
std::terminate to be invoked if an exception is thrown from the function.
The void __stdcall f3() throw(); declaration uses the syntax defined by the C++ standard. In C++17 the
throw() keyword was deprecated.
END Microsoft Specific
See also
__declspec
noexcept
Keywords
novtable
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
This is a __declspec extended attribute.
This form of __declspec can be applied to any class declaration, but should only be applied to pure interface
classes, that is, classes that will never be instantiated on their own. The __declspec stops the compiler from
generating code to initialize the vfptr in the constructor(s) and destructor of the class. In many cases, this
removes the only references to the vtable that are associated with the class and, thus, the linker will remove it.
Using this form of __declspec can result in a significant reduction in code size.
If you attempt to instantiate a class marked with novtable and then access a class member, you will receive an
access violation (AV).
Example
// novtable.cpp
#include <stdio.h>
struct __declspec(novtable) X {
virtual void mf();
};
struct Y : public X {
void mf() {
printf_s("In Y\n");
}
};
int main() {
// X *pX = new X();
// pX->mf(); // Causes a runtime access violation.
In Y
See also
__declspec
Keywords
process
3/6/2021 • 2 minutes to read • Edit Online
Specifies that your managed application process should have a single copy of a particular global variable, static
member variable, or static local variable shared across all application domains in the process. This was primarily
intended to be used when compiling with /clr:pure , which is deprecated in Visual Studio 2015 and
unsupported in Visual Studio 2017. When compiling with /clr , global and static variables are per-process by
default and do not need to use __declspec(process) .
Only a global variable, a static member variable, or a static local variable of native type can be marked with
__declspec(process) .
See also
__declspec
Keywords
property (C++)
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
This attribute can be applied to non-static "virtual data members" in a class or structure definition. The compiler
treats these "virtual data members" as data members by changing their references into function calls.
Syntax
__declspec( property( get=get_func_name ) ) declarator
__declspec( property( put=put_func_name ) ) declarator
__declspec( property( get=get_func_name, put=put_func_name ) ) declarator
Remarks
When the compiler sees a data member declared with this attribute on the right of a member-selection operator
("." or "-> "), it converts the operation to a get or put function, depending on whether such an expression is
an l-value or an r-value. In more complicated contexts, such as " += ", a rewrite is performed by doing both get
and put .
This attribute can also be used in the declaration of an empty array in a class or structure definition. For
example:
The above statement indicates that x[] can be used with one or more array indices. In this case, i=p->x[a][b]
will be turned into i=p->GetX(a, b) , and p->x[a][b] = i will be turned into p->PutX(a, b, i);
END Microsoft Specific
Example
// declspec_property.cpp
struct S {
int i;
void putprop(int j) {
i = j;
}
int getprop() {
return i;
}
int main() {
S s;
s.the_prop = 5;
return s.the_prop;
}
See also
__declspec
Keywords
restrict
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
When applied to a function declaration or definition that returns a pointer type, restrict tells the compiler that
the function returns an object that is not aliased, that is, referenced by any other pointers. This allows the
compiler to perform additional optimizations.
Syntax
__declspec(restrict) pointer_return_type function();
Remarks
The compiler propagates __declspec(restrict) . For example, the CRT malloc function has a
__declspec(restrict) decoration, and therefore, the compiler assumes that pointers initialized to memory
locations by malloc are also not aliased by previously existing pointers.
The compiler does not check that the returned pointer is not actually aliased. It is the developer's responsibility
to ensure the program does not alias a pointer marked with the restrict __declspec modifier.
For similar semantics on variables, see __restrict.
For another annotation that applies to aliasing within a function, see __declspec(noalias).
For information about the restrict keyword that is part of C++ AMP, see restrict (C++ AMP).
Example
The following sample demonstrates the use of __declspec(restrict) .
When __declspec(restrict) is applied to a function that returns a pointer, this tells the compiler that the
memory pointed to by the return value is not aliased. In this example, the pointers mempool and memptr are
global, so the compiler can't be sure that the memory they refer to is not aliased. However, they are used within
ma and its caller init in a way that returns memory that isn't otherwise referenced by the program, so
__decslpec(restrict) is used to help the optimizer. This is similar to how the CRT headers decorate allocation
functions such as malloc by using __declspec(restrict) to indicate that they always return memory that
cannot be aliased by existing pointers.
// declspec_restrict.c
// Compile with: cl /W4 declspec_restrict.c
#include <stdio.h>
#include <stdlib.h>
#define M 800
#define N 600
#define P 700
a = ma(m * n);
if (!a) exit(1);
for (i=0; i<m; i++)
for (j=0; j<n; j++)
a[i*n+j] = 0.1f/k++;
return a;
}
int main()
{
float * a, * b, * c;
if (!mempool)
{
puts("ERROR: Malloc returned null");
exit(1);
}
memptr = mempool;
a = init(M, N);
b = init(N, P);
c = init(M, P);
multiply(a, b, c);
}
Microsoft Specific
Tells the compiler not to insert buffer overrun security checks for a function.
Syntax
__declspec( safebuffers )
Remarks
The /GS compiler option causes the compiler to test for buffer overruns by inserting security checks on the
stack. The types of data structures that are eligible for security checks are described in /GS (Buffer Security
Check). For more information about buffer overrun detection, see Security Features in MSVC.
An expert manual code review or external analysis might determine that a function is safe from a buffer
overrun. In that case, you can suppress security checks for a function by applying the __declspec(safebuffers)
keyword to the function declaration.
Cau t i on
Buffer security checks provide important security protection and have a negligible affect on performance.
Therefore, we recommend that you do not suppress them, except in the rare case where the performance of a
function is a critical concern and the function is known to be safe.
Inline Functions
A primary function can use an inlining keyword to insert a copy of a secondary function. If the
__declspec(safebuffers) keyword is applied to a function, buffer overrun detection is suppressed for that
function. However, inlining affects the __declspec(safebuffers) keyword in the following ways.
Suppose the /GS compiler option is specified for both functions, but the primary function specifies the
__declspec(safebuffers) keyword. The data structures in the secondary function make it eligible for security
checks, and the function does not suppress those checks. In this case:
Specify the __forceinline keyword on the secondary function to force the compiler to inline that function
regardless of compiler optimizations.
Because the secondary function is eligible for security checks, security checks are also applied to the
primary function even though it specifies the __declspec(safebuffers) keyword.
Example
The following code shows how to use the __declspec(safebuffers) keyword.
// compile with: /c /GS
typedef struct {
int x[20];
} BUFFER;
static int checkBuffers() {
BUFFER cb;
// Use the buffer...
return 0;
};
static __declspec(safebuffers)
int noCheckBuffers() {
BUFFER ncb;
// Use the buffer...
return 0;
}
int wmain() {
checkBuffers();
noCheckBuffers();
return 0;
}
See also
__declspec
Keywords
inline, __inline, __forceinline
strict_gs_check
selectany
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Tells the compiler that the declared global data item (variable or object) is a pick-any COMDAT (a packaged
function).
Syntax
__declspec( selectany ) declarator
Remarks
At link time, if multiple definitions of a COMDAT are seen, the linker picks one and discards the rest. If the linker
option /OPT:REF (Optimizations) is selected, then COMDAT elimination will occur to remove all the
unreferenced data items in the linker output.
Constructors and assignment by global function or static methods in the declaration do not create a reference
and will not prevent /OPT:REF elimination. Side effects from such code should not be depended on when no
other references to the data exist.
For dynamically initialized, global objects, selectany will discard an unreferenced object's initialization code, as
well.
A global data item can normally be initialized only once in an EXE or DLL project. selectany can be used in
initializing global data defined by headers, when the same header appears in more than one source file.
selectany is available in both the C and C++ compilers.
NOTE
selectany can only be applied to the actual initialization of global data items that are externally visible.
__declspec(selectany) X x(1);
// selectany2.cpp
// in the following lines, const marks the variables as read only
__declspec(selectany) extern const int ix = 5;
__declspec(selectany) extern const int jx = 5;
int main() {
int ij;
ij = ix + jx;
}
See also
__declspec
Keywords
spectre
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Tells the compiler not to insert Spectre variant 1 speculative execution barrier instructions for a function.
Syntax
__declspec( spectre(nomitigation) )
Remarks
The /Qspectre compiler option causes the compiler to insert speculative execution barrier instructions. They're
inserted where analysis indicates that a Spectre variant 1 security vulnerability exists. The specific instructions
emitted depend on the processor. While these instructions should have a minimal impact on code size or
performance, there may be cases where your code is not affected by the vulnerability, and requires maximum
performance.
Expert analysis might determine that a function is safe from a Spectre variant 1 bounds check bypass defect. In
that case, you can suppress the generation of mitigation code within a function by applying
__declspec(spectre(nomitigation)) to the function declaration.
Cau t i on
The /Qspectre speculative execution barrier instructions provide important security protection and have a
negligible affect on performance. Therefore, we recommend that you do not suppress them, except in the rare
case where the performance of a function is a critical concern and the function is known to be safe.
Example
The following code shows how to use __declspec(spectre(nomitigation)) .
int main() {
noSpectreIssues();
return 0;
}
See also
__declspec
Keywords
/Qspectre
thread
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The thread extended storage-class modifier is used to declare a thread local variable. For the portable
equivalent in C++11 and later, use the thread_local storage class specifier for portable code. On Windows
thread_local is implemented with __declspec(thread) .
Syntax
__declspec(thread) declarator
Remarks
Thread Local Storage (TLS) is the mechanism by which each thread in a multithreaded process allocates storage
for thread-specific data. In standard multithreaded programs, data is shared among all threads of a given
process, whereas thread local storage is the mechanism for allocating per-thread data. For a complete
discussion of threads, see Multithreading.
Declarations of thread local variables must use extended attribute syntax and the __declspec keyword with the
thread keyword. For example, the following code declares an integer thread local variable and initializes it with
a value:
When using thread-local variables in dynamically-loaded libraries, you need to be aware of factors that can
cause a thread-local variable to not be initialized correctly:
1. If the variable is initialized with a function call (including constructors), this function will only be called for
the thread that caused the binary/DLL to load into the process, and for those threads that started after
the binary/DLL was loaded. The initialization functions are not called for any other thread that was
already running when the DLL was loaded. Dynamic initialization occurs on the DllMain call for
DLL_THREAD_ATTACH, but the DLL never gets that message if the DLL isn't in the process when the
thread starts.
2. Thread-local variables that are initialized statically with constant values are generally initialized properly
on all threads. However, as of December 2017 there is a known conformance issue in the Microsoft C++
compiler whereby constexpr variables receive dynamic rather than static initialization.
Note: Both of these issues are expected to be fixed in future updates of the compiler.
Additionally, you must observe these guidelines when declaring thread local objects and variables:
You can apply the thread attribute only to class and data declarations and definitions; thread can't be
used on function declarations or definitions.
You can specify the thread attribute only on data items with static storage duration. This includes global
data objects (both static and extern ), local static objects, and static data members of classes. You can't
declare automatic data objects with the thread attribute.
You must use the thread attribute for the declaration and the definition of a thread local object, whether
the declaration and definition occur in the same file or separate files.
You can't use the thread attribute as a type modifier.
Because the declaration of objects that use the thread attribute is permitted, these two examples are
semantically equivalent:
// declspec_thread_2.cpp
// compile with: /LD
__declspec( thread ) class B {
public:
int data;
} BObject; // BObject declared thread local.
class B2 {
public:
int data;
};
__declspec( thread ) B2 BObject2; // BObject2 declared thread local.
Standard C permits initialization of an object or variable with an expression involving a reference to itself,
but only for nonstatic objects. Although C++ normally permits such dynamic initialization of an object
with an expression involving a reference to itself, this type of initialization isn't permitted with thread local
objects. For example:
// declspec_thread_3.cpp
// compile with: /LD
#define Thread __declspec( thread )
int j = j; // Okay in C++; C error
Thread int tls_i = sizeof( tls_i ); // Okay in C and C++
A sizeof expression that includes the object being initialized does not constitute a reference to itself and
is allowed in C and C++.
END Microsoft Specific
See also
__declspec
Keywords
Thread Local Storage (TLS)
uuid (C++)
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The compiler attaches a GUID to a class or structure declared or defined (full COM object definitions only) with
the uuid attribute.
Syntax
__declspec( uuid("ComObjectGUID") ) declarator
Remarks
The uuid attribute takes a string as its argument. This string names a GUID in normal registry format with or
without the { } delimiters. For example:
This attribute can be applied in a redeclaration. This allows the system headers to supply the definitions of
interfaces such as IUnknown , and the redeclaration in some other header (such as <comdef.h>) to supply the
GUID.
The keyword __uuidof can be applied to retrieve the constant GUID attached to a user-defined type.
END Microsoft Specific
See also
__declspec
Keywords
__restrict
3/6/2021 • 2 minutes to read • Edit Online
Like the __declspec ( restrict ) modifier, the __restrict keyword (two leading underscores '_') indicates that
a symbol isn't aliased in the current scope. The __restrict keyword differs from the __declspec (restrict)
modifier in the following ways:
The __restrict keyword is valid only on variables, and __declspec (restrict) is only valid on function
declarations and definitions.
__restrict is similar to restrict for C starting in C99, but __restrict can be used in both C++ and C
programs.
When __restrict is used, the compiler won't propagate the no-alias property of a variable. That is, if you
assign a __restrict variable to a non- __restrict variable, the compiler will still allow the non-__restrict
variable to be aliased. This is different from the behavior of the C99 C language restrict keyword.
Generally, if you want to affect the behavior of an entire function, use __declspec (restrict) instead of the
keyword.
For compatibility with previous versions, _restrict is a synonym for __restrict unless compiler option /Za
(Disable language extensions) is specified.
In Visual Studio 2015 and later, __restrict can be used on C++ references.
NOTE
When used on a variable that also has the volatile keyword, volatile will take precedence.
Example
// __restrict_keyword.c
// compile with: /LD
// In the following function, declare a and b as disjoint arrays
// but do not have same assurance for c and d.
void sum2(int n, int * __restrict a, int * __restrict b,
int * c, int * d) {
int i;
for (i = 0; i < n; i++) {
a[i] = b[i] + c[i];
c[i] = b[i] + d[i];
}
}
See also
Keywords
__sptr, __uptr
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Use the __sptr or __uptr modifier on a 32-bit pointer declaration to specify how the compiler converts a 32-
bit pointer to a 64-bit pointer. A 32-bit pointer is converted, for example, when it is assigned to a 64-bit pointer
variable or is dereferenced on a 64-bit platform.
Microsoft documentation for support of 64-bit platforms sometimes refers to the most significant bit of a 32-bit
pointer as the sign bit. By default, the compiler uses sign extension to convert a 32-bit pointer to a 64-bit
pointer. That is, the least significant 32 bits of the 64-bit pointer are set to the value of the 32-bit pointer and the
most significant 32 bits are set to the value of the sign bit of the 32-bit pointer. This conversion yields correct
results if the sign bit is 0, but not if the sign bit is 1. For example, the 32-bit address 0x7FFFFFFF yields the
equivalent 64-bit address 0x000000007FFFFFFF, but the 32-bit address 0x80000000 is incorrectly changed to
0xFFFFFFFF80000000.
The __sptr , or signed pointer, modifier specifies that a pointer conversion set the most significant bits of a 64-
bit pointer to the sign bit of the 32-bit pointer. The __uptr , or unsigned pointer, modifier specifies that a
conversion set the most significant bits to zero. The following declarations show the __sptr and __uptr
modifiers used with two unqualified pointers, two pointers qualified with the __ptr32 type, and a function
parameter.
Use the __sptr and __uptr modifiers with pointer declarations. Use the modifiers in the position of a pointer
type qualifier, which means the modifier must follow the asterisk. You cannot use the modifiers with pointers to
members. The modifiers do not affect non-pointer declarations.
For compatibility with previous versions, _sptr and _uptr are synonyms for __sptr and __uptr unless
compiler option /Za (Disable language extensions) is specified.
Example
The following example declares 32-bit pointers that use the __sptr and __uptr modifiers, assigns each 32-bit
pointer to a 64-bit pointer variable, and then displays the hexadecimal value of each 64-bit pointer. The example
is compiled with the native 64-bit compiler and is executed on a 64-bit platform.
// sptr_uptr.cpp
// processor: x64
#include "stdio.h"
int main()
{
void * __ptr64 p64;
void * __ptr32 p32d; //default signed pointer
void * __sptr __ptr32 p32s; //explicit signed pointer
void * __uptr __ptr32 p32u; //explicit unsigned pointer
// The printf() function automatically displays leading zeroes with each 32-bit pointer. These are unrelated
// to the __sptr and __uptr modifiers.
printf("Display each 32-bit pointer (as an unsigned 64-bit pointer):\n");
printf("p32d: %p\n", p32d);
printf("p32s: %p\n", p32s);
printf("p32u: %p\n", p32u);
See also
Microsoft-Specific Modifiers
__unaligned
3/6/2021 • 2 minutes to read • Edit Online
Microsoft-specific . When you declare a pointer with the __unaligned modifier, the compiler assumes that the
pointer addresses data that is not aligned. Consequently, platform-appropriate code is generated to handle
unaligned reads and writes through the pointer.
Remarks
This modifier describes the alignment of the data addressed by the pointer; the pointer itself is assumed to be
aligned.
The necessity for the __unaligned keyword varies by platform and environment. Failure to mark data
appropriately can result in issues ranging from performance penalties to hardware faults. The __unaligned
modifier is not valid for the x86 platform.
For compatibility with previous versions, _unaligned is a synonym for __unaligned unless compiler option
/Za (Disable language extensions) is specified.
alignof Operator
pack
See also
Keywords
__w64
3/6/2021 • 2 minutes to read • Edit Online
This Microsoft-specific keyword is obsolete. In versions of Visual Studio earlier than Visual Studio 2013, this lets
you mark variables, so that when you compile with /Wp64 the compiler will report any warnings that would be
reported if you were compiling with a 64-bit compiler.
Syntax
type __w64 identifier
Parameters
type
One of the three types that could cause problems in code being ported from a 32-bit to a 64-bit compiler: int ,
long , or a pointer.
identifier
The identifier for the variable you are creating.
Remarks
IMPORTANT
The /Wp64 compiler option and __w64 keyword are deprecated in Visual Studio 2010 and Visual Studio 2013 and
removed starting in Visual Studio 2013. If you use the /Wp64 compiler option on the command line, the compiler issues
Command-Line Warning D9002. The __w64 keyword is silently ignored. Instead of using this option and keyword to
detect 64-bit portability issues, use a Microsoft C++ compiler that targets a 64-bit platform. For more information, see
Configure Visual C++ for 64-bit, x64 targets.
Any typedef that has __w64 on it must be 32 bits on x86 and 64 bits on x64.
To detect portability issues by using versions of the Microsoft C++ compiler earlier than Visual Studio 2010, the
__w64 keyword should be specified on any typedefs that change size between 32 bit and 64 bit platforms. For
any such type, __w64 must appear only on the 32-bit definition of the typedef.
For compatibility with previous versions, _w64 is a synonym for __w64 unless compiler option /Za (Disable
language extensions) is specified.
The __w64 keyword is ignored if the compilation does not use /Wp64 .
For more information about porting to 64-bit, see the following topics:
MSVC Compiler Options
Porting 32-Bit Code to 64-Bit Code
Configure Visual C++ for 64-bit, x64 targets
Example
// __w64.cpp
// compile with: /W3 /Wp64
typedef int Int_32;
#ifdef _WIN64
typedef __int64 Int_Native;
#else
typedef int __w64 Int_Native;
#endif
int main() {
Int_32 i0 = 5;
Int_Native i1 = 10;
i0 = i1; // C4244 64-bit int assigned to 32-bit int
See also
Keywords
func
3/6/2021 • 2 minutes to read • Edit Online
(C++11) The predefined identifier __func__ is implicitly defined as a string that contains the unqualified and
unadorned name of the enclosing function. __func__ is mandated by the C++ standard and is not a Microsoft
extension.
Syntax
__func__
Return Value
Returns a null-terminated const char array of characters that contains the function name.
Example
#include <string>
#include <iostream>
namespace Test
{
struct Foo
{
static void DoSomething(int i, std::string s)
{
std::cout << __func__ << std::endl; // Output: DoSomething
}
};
}
int main()
{
Test::Foo::DoSomething(42, "Hello");
return 0;
}
Requirements
C++11
Compiler COM Support
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The Microsoft C++ compiler can directly read component object model (COM) type libraries and translate the
contents into C++ source code that can be included in the compilation. Language extensions are available to
facilitate COM programming on the client side for desktop apps.
By using the #import preprocessor directive, the compiler can read a type library and convert it into a C++
header file that describes the COM interfaces as classes. A set of #import attributes is available for user control
of the content for the resulting type library header files.
You can use the __declspec extended attribute uuid to assign a globally unique identifier (GUID) to a COM object.
The keyword __uuidof can be used to extract the GUID associated with a COM object. Another __declspec
attribute, property, can be used to specify the get and set methods for a data member of a COM object.
A set of COM support global functions and classes is provided to support the VARIANT and BSTR types,
implement smart pointers, and encapsulate the error object thrown by _com_raise_error :
Compiler COM Global Functions
_bstr_t
_com_error
_com_ptr_t
_variant_t
END Microsoft Specific
See also
Compiler COM Support Classes
Compiler COM Global Functions
Compiler COM Global Functions
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
The following routines are available:
F UN C T IO N DESC RIP T IO N
_set_com_error_handler Replaces the default function that is used for COM error-
handling.
See also
Compiler COM Support Classes
Compiler COM Support
_com_raise_error
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Throws a _com_error in response to a failure.
Syntax
void __stdcall _com_raise_error(
HRESULT hr,
IErrorInfo* perrinfo = 0
);
Parameters
hr
HRESULT information.
perrinfo
IErrorInfo object.
Remarks
_com_raise_error , which is defined in <comdef.h>, can be replaced by a user-written version of the same
name and prototype. This could be done if you want to use #import but do not want to use C++ exception
handling. In that case, a user version of _com_raise_error might decide to do a longjmp or display a message
box and halt. The user version should not return, though, because the compiler COM support code does not
expect it to return.
You can also use _set_com_error_handler to replace the default error-handling function.
By default, _com_raise_error is defined as follows:
Requirements
Header : <comdef.h>
Lib: If the wchar_t is Native Type compiler option is on, use comsuppw.lib or comsuppwd.lib. If wchar_t is
Native Type is off, use comsupp.lib. For more information, see /Zc:wchar_t (wchar_t Is Native Type).
See also
Compiler COM Global Functions
_set_com_error_handler
ConvertStringToBSTR
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Converts a char * value to a BSTR .
Syntax
BSTR __stdcall ConvertStringToBSTR(const char* pSrc)
Parameters
pSrc
A char * variable.
Example
// ConvertStringToBSTR.cpp
#include <comutil.h>
#include <stdio.h>
int main() {
char* lpszText = "Test";
printf_s("char * text: %s\n", lpszText);
SysFreeString(bstrText);
}
Requirements
Header : <comutil.h>
Lib: comsuppw.lib or comsuppwd.lib (see /Zc:wchar_t (wchar_t Is Native Type) for more information)
See also
Compiler COM Global Functions
ConvertBSTRToString
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Converts a BSTR value to a char * .
Syntax
char* __stdcall ConvertBSTRToString(BSTR pSrc);
Parameters
pSrc
A BSTR variable.
Remarks
Conver tBSTRToString allocates a string you must delete.
Example
// ConvertBSTRToString.cpp
#include <comutil.h>
#include <stdio.h>
int main() {
BSTR bstrText = ::SysAllocString(L"Test");
wprintf_s(L"BSTR text: %s\n", bstrText);
SysFreeString(bstrText);
delete[] lpszText2;
}
Requirements
Header : <comutil.h>
Lib: comsuppw.lib or comsuppwd.lib (see /Zc:wchar_t (wchar_t Is Native Type) for more information)
See also
Compiler COM Global Functions
_set_com_error_handler
3/6/2021 • 2 minutes to read • Edit Online
Replaces the default function that is used for COM error-handling. _set_com_error_handler is Microsoft-
specific.
Syntax
void __stdcall _set_com_error_handler(
void (__stdcall *pHandler)(
HRESULT hr,
IErrorInfo* perrinfo
)
);
Parameters
pHandler
Pointer to the replacement function.
hr
HRESULT information.
perrinfo
IErrorInfo object.
Remarks
By default, _com_raise_error handles all COM errors. You can change this behavior by using
_set_com_error_handler to call your own error-handling function.
The replacement function must have a signature that is equivalent to that of _com_raise_error .
Example
// _set_com_error_handler.cpp
// compile with /EHsc
#include <stdio.h>
#include <comdef.h>
#include <comutil.h>
int main()
{
_set_com_error_handler(_My_com_raise_error);
_bstr_t bstrEmpty(L"");
_ConnectionPtr Connection = NULL;
try
{
Connection.CreateInstance(__uuidof(Connection));
Connection->Open(bstrEmpty, bstrEmpty, bstrEmpty, 0);
}
catch(char* errorMessage)
{
printf("Exception raised: %s\n", errorMessage);
}
return 0;
}
Requirements
Header : <comdef.h>
Lib: If the /Zc:wchar_t compiler option is specified (the default), use comsuppw.lib or comsuppwd.lib. If the
/Zc:wchar_t- compiler option is specified, use comsupp.lib. For more information, including how to set this
option in the IDE, see /Zc:wchar_t (wchar_t Is Native Type).
See also
Compiler COM Global Functions
Compiler COM Support Classes
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Standard classes are used to support some of the COM types. The classes are defined in <comdef.h> and the
header files generated from the type library.
C L A SS P URP O SE
See also
Compiler COM Support
Compiler COM Global Functions
C++ Language Reference
_bstr_t class
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
A _bstr_t object encapsulates the BSTR data type. The class manages resource allocation and deallocation
through function calls to SysAllocString and SysFreeString and other BSTR APIs when appropriate. The
_bstr_t class uses reference counting to avoid excessive overhead.
Members
Construction
C O N ST RUC TO R DESC RIP T IO N
Operations
F UN C T IO N DESC RIP T IO N
Operators
O P ERATO R DESC RIP T IO N
Requirements
Header : <comutil.h>
Lib: comsuppw.lib or comsuppwd.lib (For more information, see /Zc:wchar_t (wchar_t is native type))
See also
Compiler COM support classes
_bstr_t::_bstr_t
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Constructs a _bstr_t object.
Syntax
_bstr_t( ) throw( );
_bstr_t(
const _bstr_t& s1
) throw( );
_bstr_t(
const char* s2
);
_bstr_t(
const wchar_t* s3
);
_bstr_t(
const _variant_t& var
);
_bstr_t(
BSTR bstr,
bool fCopy
);
Parameters
s1
A _bstr_t object to be copied.
s2
A multibyte string.
s3
A Unicode string
var
A _variant_t object.
bstr
An existing BSTR object.
fCopy
If false , the bstr argument is attached to the new object without making a copy by calling SysAllocString .
Remarks
The _bstr_t class supplies several constructors:
_bstr_t( )
Constructs a default _bstr_t object that encapsulates a null BSTR object.
_bstr_t( _bstr_t& s1 )
Constructs a _bstr_t object as a copy of another. This constructor makes a shallow copy, which increments the
reference count of the encapsulated BSTR object instead of creating a new one.
_bstr_t( char* s2 )
Constructs a _bstr_t object by calling SysAllocString to create a new BSTR object and then encapsulates it.
This constructor first performs a multibyte to Unicode conversion.
_bstr_t( wchar_t* s3 )
Constructs a _bstr_t object by calling SysAllocString to create a new BSTR object and then encapsulates it.
_bstr_t( _variant_t& var )
Constructs a _bstr_t object from a _variant_t object by first retrieving a BSTR object from the encapsulated
VARIANT object.
See also
_bstr_t class
_variant_t class
_ bstr_t::Assign
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Copies a BSTR into the BSTR wrapped by a _bstr_t .
Syntax
void Assign(
BSTR s
);
Parameters
s
A BSTR to be copied into the BSTR wrapped by a _bstr_t .
Remarks
Assign does a binary copy of the entire length of the BSTR , whatever the content.
Example
// _bstr_t_Assign.cpp
#include <comdef.h>
#include <stdio.h>
int main()
{
// creates a _bstr_t wrapper
_bstr_t bstrWrapper;
bstrWrapper.Attach(SysAllocString(OLESTR("SysAllocedString")));
wprintf_s(L"bstrWrapper = %s\n",
static_cast<wchar_t*>(bstrWrapper));
// resuse bstr
bstr= SysAllocString(OLESTR("Yet another string"));
// two wrappers, one BSTR
_bstr_t bstrWrapper2 = bstrWrapper;
*bstrWrapper.GetAddress() = bstr;
See also
_bstr_t class
_bstr_t::Attach
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Links a _bstr_t wrapper to a BSTR .
Syntax
void Attach(
BSTR s
);
Parameters
s
A BSTR to be associated with, or assigned to, the _bstr_t variable.
Remarks
If the _bstr_t was previously attached to another BSTR , the _bstr_t will clean up the BSTR resource, if no
other _bstr_t variables are using the BSTR .
Example
See _bstr_t::Assign for an example using Attach .
END Microsoft Specific
See also
_bstr_t Class
_bstr_t::copy
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Constructs a copy of the encapsulated BSTR .
Syntax
BSTR copy( bool fCopy = true ) const;
Parameters
fCopy
If true , copy returns a copy of the contained BSTR , otherwise copy returns the actual BSTR .
Remarks
Returns a newly allocated copy of the encapsulated BSTR object, or the encapsulated object itself, depending on
the parameter.
Example
STDMETHODIMP CAlertMsg::get_ConnectionStr(BSTR *pVal){ // m_bsConStr is _bstr_t
*pVal = m_bsConStr.copy();
}
See also
_bstr_t class
_bstr_t::Detach
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Returns the BSTR wrapped by a _bstr_t and detaches the BSTR from the _bstr_t .
Syntax
BSTR Detach( ) throw;
Return Value
Returns the BSTR encapsulated by the _bstr_t .
Example
See _bstr_t::Assign for an example that uses Detach .
END Microsoft Specific
See also
_bstr_t class
_bstr_t::GetAddress
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Frees any existing string and returns the address of a newly allocated string.
Syntax
BSTR* GetAddress( );
Return Value
A pointer to the BSTR wrapped by the _bstr_t .
Remarks
GetAddress affects all _bstr_t objects that share a BSTR . More than one _bstr_t can share a BSTR through
the use of the copy constructor and operator= .
Example
See _bstr_t::Assign for an example that uses GetAddress .
END Microsoft Specific
See also
_bstr_t class
_bstr_t::GetBSTR
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Points to the beginning of the BSTR wrapped by the _bstr_t .
Syntax
BSTR& GetBSTR( );
Return Value
The beginning of the BSTR wrapped by the _bstr_t .
Remarks
GetBSTR affects all _bstr_t objects that share a BSTR . More than one _bstr_t can share a BSTR through the
use of the copy constructor and operator= .
Example
See _bstr_t::Assign for an example that uses GetBSTR .
END Microsoft Specific
See also
_bstr_t class
_bstr_t::length
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Returns the number of characters in the _bstr_t , not including the terminating null, of the encapsulated BSTR .
Syntax
unsigned int length ( ) const throw( );
Remarks
END Microsoft Specific
See also
_bstr_t class
_bstr_t::operator =
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Assigns a new value to an existing _bstr_t object.
Syntax
_bstr_t& operator=(const _bstr_t& s1) throw ( );
_bstr_t& operator=(const char* s2);
_bstr_t& operator=(const wchar_t* s3);
_bstr_t& operator=(const _variant_t& var);
Parameters
s1
A _bstr_t object to be assigned to an existing _bstr_t object.
s2
A multibyte string to be assigned to an existing _bstr_t object.
s3
A Unicode string to be assigned to an existing _bstr_t object.
var
A _variant_t object to be assigned to an existing _bstr_t object.
END Microsoft Specific
Example
See _bstr_t::Assign for an example that uses operator= .
See also
_bstr_t class
_bstr_t::operator += , _bstr_t::operator +
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Appends characters to the end of the _bstr_t object, or concatenates two strings.
Syntax
_bstr_t& operator+=( const _bstr_t& s1 );
_bstr_t operator+( const _bstr_t& s1 );
friend _bstr_t operator+( const char* s2, const _bstr_t& s1);
friend _bstr_t operator+( const wchar_t* s3, const _bstr_t& s1);
Parameters
s1
A _bstr_t object.
s2
A multibyte string.
s3
A Unicode string.
Remarks
These operators perform string concatenation:
operator+=( s1 )Appends the characters in the encapsulated BSTR of s1 to the end of this object's
encapsulated BSTR .
operator+( s1 ) Returns the new _bstr_t that's formed by concatenating this object's BSTR and the
one in s1 .
operator+( s2, s1 )Returns a new _bstr_t that's formed by concatenating a multibyte string s2 ,
converted to Unicode, and the BSTR encapsulated in s1 .
operator+( s3, s1 ) Returns a new _bstr_t that's formed by concatenating a Unicode string s3 and
the BSTR encapsulated in s1 .
END Microsoft Specific
See also
_bstr_t class
_bstr_t::operator !
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Checks if the encapsulated BSTR is a NULL string.
Syntax
bool operator!( ) const throw( );
Return Value
It returns true if the encapsulated BSTR is a NULL string, false if not.
END Microsoft Specific
See also
_bstr_t class
_bstr_t relational operators
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Compares two _bstr_t objects.
Syntax
bool operator==(const _bstr_t& str) const throw( );
bool operator!=(const _bstr_t& str) const throw( );
bool operator<(const _bstr_t& str) const throw( );
bool operator>(const _bstr_t& str) const throw( );
bool operator<=(const _bstr_t& str) const throw( );
bool operator>=(const _bstr_t& str) const throw( );
Remarks
These operators compare two _bstr_t objects lexicographically. The operators return true if the comparisons
hold, otherwise return false .
END Microsoft Specific
See also
_bstr_t class
_bstr_t::wchar_t* , _bstr_t::char*
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Returns the BSTR characters as a narrow or wide character array.
Syntax
operator const wchar_t*( ) const throw( );
operator wchar_t*( ) const throw( );
operator const char*( ) const;
operator char*( ) const;
Remarks
These operators can be used to extract the character data that's encapsulated by the BSTR object. Assigning a
new value to the returned pointer does not modify the original BSTR data.
END Microsoft Specific
See also
_bstr_t class
_com_error Class
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
A _com_error object represents an exception condition detected by the error-handling wrapper functions in the
header files generated from the type library or by one of the COM support classes. The _com_error class
encapsulates the HRESULT error code and any associated IErrorInfo Interface object.
Construction
NAME DESC RIP T IO N
Operators
NAME DESC RIP T IO N
Extractor Functions
NAME DESC RIP T IO N
IErrorInfo Functions
NAME DESC RIP T IO N
Requirements
Header : <comdef.h>
Lib: comsuppw.lib or comsuppwd.lib (see /Zc:wchar_t (wchar_t Is Native Type) for more information)
See also
Compiler COM Support Classes
IErrorInfo Interface
_com_error Member Functions
3/6/2021 • 2 minutes to read • Edit Online
For information about the _com_error member functions, see _com_error Class.
See also
_com_error Class
_com_error::_com_error
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Constructs a _com_error object.
Syntax
_com_error(
HRESULT hr,
IErrorInfo* perrinfo = NULL,
bool fAddRef=false) throw( );
Parameters
hr
HRESULT information.
perrinfo
IErrorInfo object.
fAddRef
The default causes the constructor to call AddRef on a non-null IErrorInfo interface. This provides for correct
reference counting in the common case where ownership of the interface is passed into the _com_error object,
such as:
If you do not want your code to transfer ownership to the _com_error object, and the AddRef is required to
offset the Release in the _com_error destructor, construct the object as follows:
that
An existing _com_error object.
Remarks
The first constructor creates a new object given an HRESULT and optional IErrorInfo object. The second creates
a copy of an existing _com_error object.
END Microsoft Specific
See also
_com_error Class
_com_error::Description
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls IErrorInfo::GetDescription function.
Syntax
_bstr_t Description( ) const;
Return Value
Returns the result of IErrorInfo::GetDescription for the IErrorInfo object recorded within the _com_error
object. The resulting BSTR is encapsulated in a _bstr_t object. If no IErrorInfo is recorded, it returns an
empty _bstr_t .
Remarks
Calls the IErrorInfo::GetDescription function and retrieves IErrorInfo recorded within the _com_error object.
Any failure while calling the IErrorInfo::GetDescription method is ignored.
END Microsoft Specific
See also
_com_error Class
_com_error::Error
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Retrieves the HRESULT passed to the constructor.
Syntax
HRESULT Error( ) const throw( );
Return Value
Raw HRESULT item passed into the constructor.
Remarks
Retrieves the encapsulated HRESULT item in a _com_error object.
END Microsoft Specific
See also
_com_error Class
_com_error::ErrorInfo
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Retrieves the IErrorInfo object passed to the constructor.
Syntax
IErrorInfo * ErrorInfo( ) const throw( );
Return Value
Raw IErrorInfo item passed into the constructor.
Remarks
Retrieves the encapsulated IErrorInfo item in a _com_error object, or NULL if no IErrorInfo item is recorded.
The caller must call Release on the returned object when finished using it.
END Microsoft Specific
See also
_com_error Class
_com_error::ErrorMessage
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Retrieves the string message for HRESULT stored in the _com_error object.
Syntax
const TCHAR * ErrorMessage( ) const throw( );
Return Value
Returns the string message for the HRESULT recorded within the _com_error object. If the HRESULT is a mapped
16-bit wCode, then a generic message " IDispatch error #<wCode> " is returned. If no message is found, then a
generic message " Unknown error #<hresult> " is returned. The returned string is either a Unicode or multibyte
string, depending on the state of the _UNICODE macro.
Remarks
Retrieves the appropriate system message text for HRESULT recorded within the _com_error object. The system
message text is obtained by calling the Win32 FormatMessage function. The string returned is allocated by the
FormatMessage API, and it is released when the _com_error object is destroyed.
See also
_com_error Class
_com_error::GUID
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls IErrorInfo::GetGUID function.
Syntax
GUID GUID( ) const throw( );
Return Value
Returns the result of IErrorInfo::GetGUID for the IErrorInfo object recorded within the _com_error object. If
no IErrorInfo object is recorded, it returns GUID_NULL .
Remarks
Any failure while calling the IErrorInfo::GetGUID method is ignored.
END Microsoft Specific
See also
_com_error Class
_com_error::HelpContext
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls IErrorInfo::GetHelpContext function.
Syntax
DWORD HelpContext( ) const throw( );
Return Value
Returns the result of IErrorInfo::GetHelpContext for the IErrorInfo object recorded within the _com_error
object. If no IErrorInfo object is recorded, it returns a zero.
Remarks
Any failure while calling the IErrorInfo::GetHelpContext method is ignored.
END Microsoft Specific
See also
_com_error Class
_com_error::HelpFile
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls IErrorInfo::GetHelpFile function.
Syntax
_bstr_t HelpFile() const;
Return Value
Returns the result of IErrorInfo::GetHelpFile for the IErrorInfo object recorded within the _com_error object.
The resulting BSTR is encapsulated in a _bstr_t object. If no IErrorInfo is recorded, it returns an empty
_bstr_t .
Remarks
Any failure while calling the IErrorInfo::GetHelpFile method is ignored.
END Microsoft Specific
See also
_com_error Class
_com_error::HRESULTToWCode
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Maps 32-bit HRESULT to 16-bit wCode .
Syntax
static WORD HRESULTToWCode(
HRESULT hr
) throw( );
Parameters
hr
The 32-bit HRESULT to be mapped to 16-bit wCode .
Return Value
16-bit wCode mapped from the 32-bit HRESULT.
Remarks
See _com_error::WCode for more information.
END Microsoft Specific
See also
_com_error::WCode
_com_error::WCodeToHRESULT
_com_error Class
_com_error::Source
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls IErrorInfo::GetSource function.
Syntax
_bstr_t Source() const;
Return Value
Returns the result of IErrorInfo::GetSource for the IErrorInfo object recorded within the _com_error object.
The resulting BSTR is encapsulated in a _bstr_t object. If no IErrorInfo is recorded, it returns an empty
_bstr_t .
Remarks
Any failure while calling the IErrorInfo::GetSource method is ignored.
END Microsoft Specific
See also
_com_error Class
_com_error::WCode
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Retrieves the 16-bit error code mapped into the encapsulated HRESULT.
Syntax
WORD WCode ( ) const throw( );
Return Value
If the HRESULT is within the range 0x80040200 to 0x8004FFFF, the WCode method returns the HRESULT minus
0x80040200; otherwise, it returns zero.
Remarks
The WCode method is used to undo a mapping that happens in the COM support code. The wrapper for a
dispinterface property or method calls a support routine that packages the arguments and calls
IDispatch::Invoke . Upon return, if a failure HRESULT of DISP_E_EXCEPTION is returned, the error information is
retrieved from the EXCEPINFO structure passed to IDispatch::Invoke . The error code can either be a 16-bit
value stored in the wCode member of the EXCEPINFO structure or a full 32-bit value in the scode member of
the EXCEPINFO structure. If a 16-bit wCode is returned, it must first be mapped to a 32-bit failure HRESULT.
END Microsoft Specific
See also
_com_error::HRESULTToWCode
_com_error::WCodeToHRESULT
_com_error Class
_com_error::WCodeToHRESULT
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Maps 16-bit wCode to 32-bit HRESULT.
Syntax
static HRESULT WCodeToHRESULT(
WORD wCode
) throw( );
Parameters
wCode
The 16-bit wCode to be mapped to 32-bit HRESULT.
Return Value
32-bit HRESULT mapped from the 16-bit wCode.
Remarks
See the WCode member function.
END Microsoft Specific
See also
_com_error::WCode
_com_error::HRESULTToWCode
_com_error Class
_com_error Operators
3/6/2021 • 2 minutes to read • Edit Online
See also
_com_error Class
_com_error::operator =
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Assigns an existing _com_error object to another.
Syntax
_com_error& operator = (
const _com_error& that
) throw ( );
Parameters
that
A _com_error object.
END Microsoft Specific
See also
_com_error Class
_com_ptr_t Class
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
A _com_ptr_t object encapsulates a COM interface pointer and is called a "smart" pointer. This template class
manages resource allocation and deallocation through function calls to the IUnknown member functions:
QueryInterface , AddRef , and Release .
A smart pointer is usually referenced by the typedef definition provided by the _COM_SMARTPTR_TYPEDEF
macro. This macro takes an interface name and the IID and declares a specialization of _com_ptr_t with the
name of the interface plus a suffix of Ptr . For example:
_COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface));
Low-Level Operations
NAME DESC RIP T IO N
operators ==, !=, <, >, <=, >= Compare the smart pointer object to another smart pointer,
raw interface pointer, or NULL.
Requirements
Header : <comip.h>
Lib: comsuppw.lib or comsuppwd.lib (see /Zc:wchar_t (wchar_t Is Native Type) for more information)
See also
Compiler COM Support Classes
_com_ptr_t Member Functions
3/6/2021 • 2 minutes to read • Edit Online
For information about the _com_ptr_t member functions, see _com_ptr_t Class.
See also
_com_ptr_t Class
_com_ptr_t::_com_ptr_t
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Constructs a _com_ptr_t object.
Syntax
// Default constructor.
// Constructs a NULL smart pointer.
_com_ptr_t() throw();
Parameters
pInterface
A raw interface pointer.
fAddRef
If true , AddRef is called to increment the reference count of the encapsulated interface pointer.
cp
A _com_ptr_t object.
p
A raw interface pointer, its type being different from the smart pointer type of this _com_ptr_t object.
varSrc
A _variant_t object.
clsid
The CLSID of a coclass.
dwClsContext
Context for running executable code.
lpcStr
A multibyte string that holds either a CLSID (starting with "{ ") or a ProgID .
pOuter
The outer unknown for aggregation.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::AddRef
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls the AddRef member function of IUnknown on the encapsulated interface pointer.
Syntax
void AddRef( );
Remarks
Calls IUnknown::AddRef on the encapsulated interface pointer, raising an E_POINTER error if the pointer is NULL.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::Attach
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Encapsulates a raw interface pointer of this smart pointer's type.
Syntax
void Attach( Interface* pInterface ) throw( );
void Attach( Interface* pInterface, bool fAddRef ) throw( );
Parameters
pInterface
A raw interface pointer.
fAddRef
If it is true , then AddRef is called. If it is false , the _com_ptr_t object takes ownership of the raw interface
pointer without calling AddRef .
Remarks
Attach( pInterface ) AddRef is not called. The ownership of the interface is passed to this _com_ptr_t
object. Release is called to decrement the reference count for the previously encapsulated pointer.
Attach( pInterface , fAddRef ) If fAddRef is true , AddRef is called to increment the reference count for the
encapsulated interface pointer. If fAddRef is false , this _com_ptr_t object takes ownership of the raw
interface pointer without calling AddRef . Release is called to decrement the reference count for the
previously encapsulated pointer.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::CreateInstance
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Creates a new instance of an object given a CLSID or ProgID .
Syntax
HRESULT CreateInstance(
const CLSID& rclsid,
IUnknown* pOuter=NULL,
DWORD dwClsContext = CLSCTX_ALL
) throw( );
HRESULT CreateInstance(
LPCWSTR clsidString,
IUnknown* pOuter=NULL,
DWORD dwClsContext = CLSCTX_ALL
) throw( );
HRESULT CreateInstance(
LPCSTR clsidStringA,
IUnknown* pOuter=NULL,
DWORD dwClsContext = CLSCTX_ALL
) throw( );
Parameters
rclsid
The CLSID of an object.
clsidString
A Unicode string that holds either a CLSID (starting with "{ ") or a ProgID .
clsidStringA
A multibyte string, using the ANSI code page, that holds either a CLSID (starting with "{ ") or a ProgID .
dwClsContext
Context for running executable code.
pOuter
The outer unknown for aggregation.
Remarks
These member functions call CoCreateInstance to create a new COM object and then queries for this smart
pointer's interface type. The resulting pointer is then encapsulated within this _com_ptr_t object. Release is
called to decrement the reference count for the previously encapsulated pointer. This routine returns the
HRESULT to indicate success or failure.
CreateInstance( rclsid , dwClsContext ) Creates a new running instance of an object given a CLSID .
CreateInstance( clsidString , dwClsContext ) Creates a new running instance of an object given a Unicode
string that holds either a CLSID (starting with "{ ") or a ProgID .
CreateInstance( clsidStringA , dwClsContext ) Creates a new running instance of an object given a
multibyte character string that holds either a CLSID (starting with "{ ") or a ProgID . Calls
MultiByteToWideChar, which assumes that the string is in the ANSI code page rather than an OEM code
page.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::Detach
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Extracts and returns the encapsulated interface pointer.
Syntax
Interface* Detach( ) throw( );
Remarks
Extracts and returns the encapsulated interface pointer, and then clears the encapsulated pointer storage to
NULL. This removes the interface pointer from encapsulation. It is up to you to call Release on the returned
interface pointer.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::GetActiveObject
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Attaches to an existing instance of an object given a CLSID or ProgID .
Syntax
HRESULT GetActiveObject(
const CLSID& rclsid
) throw( );
HRESULT GetActiveObject(
LPCWSTR clsidString
) throw( );
HRESULT GetActiveObject(
LPCSTR clsidStringA
) throw( );
Parameters
rclsid
The CLSID of an object.
clsidString
A Unicode string that holds either a CLSID (starting with "{ ") or a ProgID .
clsidStringA
A multibyte string, using the ANSI code page, that holds either a CLSID (starting with "{ ") or a ProgID .
Remarks
These member functions call GetActiveObject to retrieve a pointer to a running object that has been registered
with OLE and then queries for this smart pointer's interface type. The resulting pointer is then encapsulated
within this _com_ptr_t object. Release is called to decrement the reference count for the previously
encapsulated pointer. This routine returns the HRESULT to indicate success or failure.
GetActiveObject( rclsid ) Attaches to an existing instance of an object given a CLSID .
GetActiveObject( clsidString ) Attaches to an existing instance of an object given a Unicode string that
holds either a CLSID (starting with "{ ") or a ProgID .
GetActiveObject( clsidStringA ) Attaches to an existing instance of an object given a multibyte
character string that holds either a CLSID (starting with "{ ") or a ProgID . Calls MultiByteToWideChar,
which assumes that the string is in the ANSI code page rather than an OEM code page.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::GetInterfacePtr
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Returns the encapsulated interface pointer.
Syntax
Interface* GetInterfacePtr( ) const throw( );
Interface*& GetInterfacePtr() throw();
Remarks
Returns the encapsulated interface pointer, which may be NULL.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::QueryInterface
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls the Quer yInterface member function of IUnknown on the encapsulated interface pointer.
Syntax
template<typename _InterfaceType> HRESULT QueryInterface (
const IID& iid,
_InterfaceType*& p
) throw ( );
template<typename _InterfaceType> HRESULT QueryInterface (
const IID& iid,
_InterfaceType** p
) throw( );
Parameters
iid
IID of an interface pointer.
p
Raw interface pointer.
Remarks
Calls IUnknown::QueryInterface on the encapsulated interface pointer with the specified IID and returns the
resulting raw interface pointer in p. This routine returns the HRESULT to indicate success or failure.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t::Release
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Calls the Release member function of IUnknown on the encapsulated interface pointer.
Syntax
void Release( );
Remarks
Calls IUnknown::Release on the encapsulated interface pointer, raising an E_POINTER error if this interface
pointer is NULL.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t Operators
3/6/2021 • 2 minutes to read • Edit Online
See also
_com_ptr_t Class
_com_ptr_t::operator =
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Assigns a new value to an existing _com_ptr_t object.
Syntax
template<typename _OtherIID>
_com_ptr_t& operator=( const _com_ptr_t<_OtherIID>& p );
Remarks
Assigns an interface pointer to this _com_ptr_t object.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t Relational Operators
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Compare the smart pointer object to another smart pointer, raw interface pointer, or NULL.
Syntax
template<typename _OtherIID>
bool operator==( const _com_ptr_t<_OtherIID>& p );
template<typename _OtherIID>
bool operator==( _com_ptr_t<_OtherIID>& p );
template<typename _InterfaceType>
bool operator==( _InterfaceType* p );
template<>
bool operator==( Interface* p );
template<>
bool operator==( const _com_ptr_t& p ) throw();
template<>
bool operator==( _com_ptr_t& p ) throw();
template<typename _OtherIID>
bool operator!=( const _com_ptr_t<_OtherIID>& p );
template<typename _OtherIID>
bool operator!=( _com_ptr_t<_OtherIID>& p );
template<typename _InterfaceType>
bool operator!=( _InterfaceType* p );
template<typename _OtherIID>
bool operator<( const _com_ptr_t<_OtherIID>& p );
template<typename _OtherIID>
bool operator<( _com_ptr_t<_OtherIID>& p );
template<typename _InterfaceType>
bool operator<( _InterfaceType* p );
template<typename _OtherIID>
bool operator>( const _com_ptr_t<_OtherIID>& p );
template<typename _OtherIID>
bool operator>(_com_ptr_t< _OtherIID>& p );
template<typename _InterfaceType>
bool operator>( _InterfaceType* p );
template<typename _OtherIID>
bool operator<=( const _com_ptr_t<_OtherIID>& p );
template<typename _OtherIID>
bool operator<=( _com_ptr_t<_OtherIID>& p );
template<typename _InterfaceType>
bool operator<=( _InterfaceType* p );
template<typename _OtherIID>
bool operator>=( const _com_ptr_t<_OtherIID>& p );
template<typename _OtherIID>
bool operator>=( _com_ptr_t<_OtherIID>& p );
template<typename _InterfaceType>
bool operator>=( _InterfaceType* p );
Remarks
Compares a smart pointer object to another smart pointer, raw interface pointer, or NULL. Except for the NULL
pointer tests, these operators first query both pointers for IUnknown , and compare the results.
END Microsoft Specific
See also
_com_ptr_t Class
_com_ptr_t Extractors
11/2/2020 • 2 minutes to read • Edit Online
Microsoft-specific
Extract the encapsulated COM interface pointer.
Syntax
operator Interface*( ) const throw( );
operator Interface&( ) const;
Interface& operator*( ) const;
Interface* operator->( ) const;
Interface** operator&( ) throw( );
operator bool( ) const throw( );
Remarks
operator Interface* Returns the encapsulated interface pointer, which may be NULL.
operator Interface& Returns a reference to the encapsulated interface pointer, and issues an error if the
pointer is NULL.
operator* Allows a smart pointer object to act as though it were the actual encapsulated interface when
dereferenced.
operator->Allows a smart pointer object to act as though it were the actual encapsulated interface when
dereferenced.
operator& Releases any encapsulated interface pointer, replacing it with NULL, and returns the address of
the encapsulated pointer. This operator allows you to pass the smart pointer by address to a function that
has an out parameter through which it returns an interface pointer.
operator bool Allows a smart pointer object to be used in a conditional expression. This operator returns
true if the pointer isn't NULL.
NOTE
Because operator bool is not declared as explicit , _com_ptr_t is implicitly convertible to bool , which is
convertible to any scalar type. This can have unexpected consequences in your code. Enable Compiler Warning
(level 4) C4800 to prevent unintentional use of this conversion.
See also
_com_ptr_t class
Relational Function Templates
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Syntax
template<typename _InterfaceType> bool operator==(
int NULL,
_com_ptr_t<_InterfaceType>& p
);
template<typename _Interface,
typename _InterfacePtr> bool operator==(
_Interface* i,
_com_ptr_t<_InterfacePtr>& p
);
template<typename _Interface> bool operator!=(
int NULL,
_com_ptr_t<_Interface>& p
);
template<typename _Interface,
typename _InterfacePtr> bool operator!=(
_Interface* i,
_com_ptr_t<_InterfacePtr>& p
);
template<typename _Interface> bool operator<(
int NULL,
_com_ptr_t<_Interface>& p
);
template<typename _Interface,
typename _InterfacePtr> bool operator<(
_Interface* i,
_com_ptr_t<_InterfacePtr>& p
);
template<typename _Interface> bool operator>(
int NULL,
_com_ptr_t<_Interface>& p
);
template<typename _Interface,
typename _InterfacePtr> bool operator>(
_Interface* i,
_com_ptr_t<_InterfacePtr>& p
);
template<typename _Interface> bool operator<=(
int NULL,
_com_ptr_t<_Interface>& p
);
template<typename _Interface,
typename _InterfacePtr> bool operator<=(
_Interface* i,
_com_ptr_t<_InterfacePtr>& p
);
template<typename _Interface> bool operator>=(
int NULL,
_com_ptr_t<_Interface>& p
);
template<typename _Interface,
typename _InterfacePtr> bool operator>=(
_Interface* i,
_com_ptr_t<_InterfacePtr>& p
);
Parameters
i
A raw interface pointer.
p
A smart pointer.
Remarks
These function templates allow comparison with a smart pointer on the right side of the comparison operator.
These are not member functions of _com_ptr_t .
END Microsoft Specific
See also
_com_ptr_t Class
_variant_t Class
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
A _variant_t object encapsulates the VARIANT data type. The class manages resource allocation and
deallocation and makes function calls to VariantInit and VariantClear as appropriate.
Construction
NAME DESC RIP T IO N
Operations
NAME DESC RIP T IO N
Operators
NAME DESC RIP T IO N
Requirements
Header : <comutil.h>
Lib: comsuppw.lib or comsuppwd.lib (see /Zc:wchar_t (wchar_t Is Native Type) for more information)
See also
Compiler COM Support Classes
_variant_t Member Functions
3/6/2021 • 2 minutes to read • Edit Online
For information about the _variant_t member functions, see _variant_t Class.
See also
_variant_t Class
_variant_t::_variant_t
3/6/2021 • 4 minutes to read • Edit Online
Microsoft Specific
Constructs a _variant_t object.
Syntax
_variant_t( ) throw( );
_variant_t(
const VARIANT& varSrc
);
_variant_t(
const VARIANT* pVarSrc
);
_variant_t(
const _variant_t& var_t_Src
);
_variant_t(
VARIANT& varSrc,
bool fCopy
);
_variant_t(
short sSrc,
VARTYPE vtSrc = VT_I2
);
_variant_t(
long lSrc,
VARTYPE vtSrc = VT_I4
);
_variant_t(
float fltSrc
) throw( );
_variant_t(
double dblSrc,
VARTYPE vtSrc = VT_R8
);
_variant_t(
const CY& cySrc
) throw( );
_variant_t(
const _bstr_t& bstrSrc
);
_variant_t(
const wchar_t *wstrSrc
);
_variant_t(
const char* strSrc
);
_variant_t(
IDispatch* pDispSrc,
bool fAddRef = true
) throw( );
_variant_t(
bool bSrc
) throw( );
_variant_t(
IUnknown* pIUknownSrc,
bool fAddRef = true
) throw( );
_variant_t(
const DECIMAL& decSrc
) throw( );
_variant_t(
BYTE bSrc
) throw( );
variant_t(
char cSrc
) throw();
_variant_t(
unsigned short usSrc
) throw();
_variant_t(
unsigned long ulSrc
) throw();
_variant_t(
int iSrc
) throw();
_variant_t(
unsigned int uiSrc
) throw();
_variant_t(
__int64 i8Src
) throw();
_variant_t(
unsigned __int64 ui8Src
) throw();
Parameters
varSrc
A VARIANT object to be copied into the new _variant_t object.
pVarSrc
Pointer to a VARIANT object to be copied into the new _variant_t object.
var_t_Src
A _variant_t object to be copied into the new _variant_t object.
fCopy
If false , the supplied VARIANT object is attached to the new _variant_t object without making a new copy by
VariantCopy .
ISrc, sSrc
An integer value to be copied into the new _variant_t object.
vtSrc
The VARTYPE for the new _variant_t object.
fltSrc, dblSrc
A numerical value to be copied into the new _variant_t object.
cySrc
A CY object to be copied into the new _variant_t object.
bstrSrc
A _bstr_t object to be copied into the new _variant_t object.
strSrc, wstrSrc
A string to be copied into the new _variant_t object.
bSrc
A bool value to be copied into the new _variant_t object.
pIUknownSrc
COM interface pointer to a VT_UNKNOWN object to be encapsulated into the new _variant_t object.
pDispSrc
COM interface pointer to a VT_DISPATCH object to be encapsulated into the new _variant_t object.
decSrc
A DECIMAL value to be copied into the new _variant_t object.
bSrc
A BYTE value to be copied into the new _variant_t object.
cSrc
A char value to be copied into the new _variant_t object.
usSrc
A unsigned short value to be copied into the new _variant_t object.
ulSrc
A unsigned long value to be copied into the new _variant_t object.
iSrc
An int value to be copied into the new _variant_t object.
uiSrc
An unsigned int value to be copied into the new _variant_t object.
i8Src
An __int64 value to be copied into the new _variant_t object.
ui8Src
An unsigned __int64 value to be copied into the new _variant_t object.
Remarks
_variant_t( ) Constructs an empty _variant_t object, VT_EMPTY .
_variant_t( VARIANT& varSrc ) Constructs a _variant_t object from a copy of the VARIANT object. The
variant type is retained.
_variant_t( VARIANT * pVarSrc ) Constructs a _variant_t object from a copy of the VARIANT object. The
variant type is retained.
_variant_t( _variant_t& var_t_Src ) Constructs a _variant_t object from another _variant_t object.
The variant type is retained.
_variant_t( VARIANT& varSrc , bool fCopy ) Constructs a _variant_t object from an existing VARIANT
object. If fCopy is false , the VARIANT object is attached to the new object without making a copy.
_variant_t( shor t sSrc , VARTYPE vtSrc = VT_I2 ) Constructs a _variant_t object of type VT_I2 or
VT_BOOL from a short integer value. Any other VARTYPE results in an E_INVALIDARG error.
_variant_t( long lSrc , VARTYPE vtSrc = VT_I4 ) Constructs a _variant_t object of type VT_I4,
VT_BOOL, or VT_ERROR from a long integer value. Any other VARTYPE results in an E_INVALIDARG
error.
_variant_t( float fltSrc ) Constructs a _variant_t object of type VT_R4 from a float numerical value.
_variant_t( double dblSrc , VARTYPE vtSrc = VT_R8 ) Constructs a _variant_t object of type VT_R8
or VT_DATE from a double numerical value. Any other VARTYPE results in an E_INVALIDARG error.
_variant_t( CY& cySrc ) Constructs a _variant_t object of type VT_CY from a CY object.
_variant_t( _bstr_t& bstrSrc ) Constructs a _variant_t object of type VT_BSTR from a _bstr_t object.
A new BSTR is allocated.
_variant_t( wchar_t * wstrSrc ) Constructs a _variant_t object of type VT_BSTR from a Unicode string.
A new BSTR is allocated.
_variant_t( char * strSrc ) Constructs a _variant_t object of type VT_BSTR from a string. A new BSTR
is allocated.
_variant_t( bool bSrc ) Constructs a _variant_t object of type VT_BOOL from a bool value.
_variant_t( IUnknown * pIUknownSrc , bool fAddRef = true ) Constructs a _variant_t object of type
VT_UNKNOWN from a COM interface pointer. If fAddRef is true , then AddRef is called on the supplied
interface pointer to match the call to Release that will occur when the _variant_t object is destroyed. It
is up to you to call Release on the supplied interface pointer. If fAddRef is false , this constructor takes
ownership of the supplied interface pointer; do not call Release on the supplied interface pointer.
_variant_t( IDispatch * pDispSrc , bool fAddRef = true ) Constructs a _variant_t object of type
VT_DISPATCH from a COM interface pointer. If fAddRef is true , then AddRef is called on the supplied
interface pointer to match the call to Release that will occur when the _variant_t object is destroyed. It
is up to you to call Release on the supplied interface pointer. If fAddRef is false , this constructor takes
ownership of the supplied interface pointer; do not call Release on the supplied interface pointer.
_variant_t( DECIMAL& decSrc ) Constructs a _variant_t object of type VT_DECIMAL from a DECIMAL
value.
_variant_t( BYTE bSrc ) Constructs a _variant_t object of type VT_UI1 from a BYTE value.
See also
_variant_t Class
_variant_t::Attach
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Attaches a VARIANT object into the _variant_t object.
Syntax
void Attach(VARIANT& varSrc);
Parameters
varSrc
A VARIANT object to be attached to this _variant_t object.
Remarks
Takes ownership of the VARIANT by encapsulating it. This member function releases any existing encapsulated
VARIANT , then copies the supplied VARIANT , and sets its VARTYPE to VT_EMPTY to make sure its resources can
only be released by the _variant_t destructor.
END Microsoft Specific
See also
_variant_t Class
_variant_t::Clear
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Clears the encapsulated VARIANT object.
Syntax
void Clear( );
Remarks
Calls VariantClear on the encapsulated VARIANT object.
END Microsoft Specific
See also
_variant_t Class
_variant_t::ChangeType
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Changes the type of the _variant_t object to the indicated VARTYPE .
Syntax
void ChangeType(
VARTYPE vartype,
const _variant_t* pSrc = NULL
);
Parameters
vartype
The VARTYPE for this _variant_t object.
pSrc
A pointer to the _variant_t object to be converted. If this value is NULL, conversion is done in place.
Remarks
This member function converts a _variant_t object into the indicated VARTYPE . If pSrc is NULL, the conversion
is done in place, otherwise this _variant_t object is copied from pSrc and then converted.
END Microsoft Specific
See also
_variant_t Class
_variant_t::Detach
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Detaches the encapsulated VARIANT object from this _variant_t object.
Syntax
VARIANT Detach( );
Return Value
The encapsulated VARIANT .
Remarks
Extracts and returns the encapsulated VARIANT , then clears this _variant_t object without destroying it. This
member function removes the VARIANT from encapsulation and sets the VARTYPE of this _variant_t object to
VT_EMPTY. It is up to you to release the returned VARIANT by calling the VariantClear function.
END Microsoft Specific
See also
_variant_t Class
_variant_t::SetString
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Assigns a string to this _variant_t object.
Syntax
void SetString(const char* pSrc);
Parameters
pSrc
Pointer to the character string.
Remarks
Converts an ANSI character string to a Unicode BSTR string and assigns it to this _variant_t object.
END Microsoft Specific
See also
_variant_t Class
_variant_t Operators
3/6/2021 • 2 minutes to read • Edit Online
See also
_variant_t Class
_variant_t::operator=
3/29/2021 • 2 minutes to read • Edit Online
Syntax
_variant_t& operator=( const VARIANT& varSrc );
_variant_t& operator=( const VARIANT* pVarSrc );
_variant_t& operator=( const _variant_t& var_t_Src );
_variant_t& operator=( short sSrc );
_variant_t& operator=( long lSrc );
_variant_t& operator=( float fltSrc );
_variant_t& operator=( double dblSrc );
_variant_t& operator=( const CY& cySrc );
_variant_t& operator=( const _bstr_t& bstrSrc );
_variant_t& operator=( const wchar_t* wstrSrc );
_variant_t& operator=( const char* strSrc );
_variant_t& operator=( IDispatch* pDispSrc );
_variant_t& operator=( bool bSrc );
_variant_t& operator=( IUnknown* pSrc );
_variant_t& operator=( const DECIMAL& decSrc );
_variant_t& operator=( BYTE byteSrc );
_variant_t& operator=( char cSrc );
_variant_t& operator=( unsigned short usSrc );
_variant_t& operator=( unsigned long ulSrc );
_variant_t& operator=( int iSrc );
_variant_t& operator=( unsigned int uiSrc );
_variant_t& operator=( __int64 i8Src );
_variant_t& operator=( unsigned __int64 ui8Src );
Parameters
varSrc
A reference to a VARIANT from which to copy the content and VT_* type.
pVarSrc
A pointer to a VARIANT from which to copy the content and VT_* type.
var_t_Src
A reference to a _variant_t from which to copy the content and VT_* type.
sSrc
A short integer value to copy. Given type VT_BOOL if *this is of type VT_BOOL . Otherwise, it's given type
VT_I2 .
lSrc
A long integer value to copy. Given type VT_BOOL if *this is of type VT_BOOL . Given type VT_ERROR if *this
is of type VT_ERROR . Otherwise, given type VT_I4 .
fltSrc
A float numerical value to copy. Given type VT_R4 .
dblSrc
A double numerical value to copy. Given type VT_DATE if this is of type VT_DATE . Otherwise, given type
VT_R8 .
cySrc
A CY object to copy. Given type VT_CY .
bstrSrc
A BSTR object to copy. Given type VT_BSTR .
wstrSrc
A Unicode string to copy, stored as a BSTR and given type VT_BSTR .
strSrc
A multibyte string to copy, stored as a BSTR and given type VT_BSTR .
pDispSrc
An IDispatch pointer to copy with a call to AddRef . Given type VT_DISPATCH .
bSrc
A bool value to copy. Given type VT_BOOL .
pSrc
An IUnknown pointer to copy with a call to AddRef . Given type VT_UNKNOWN .
decSrc
A DECIMAL object to copy. Given type VT_DECIMAL .
byteSrc
A BYTE value to copy. Given type VT_UI1 .
cSrc
A char value to copy. Given type VT_I1 .
usSrc
An unsigned short value to copy. Given type VT_UI2 .
ulSrc
An unsigned long value to copy. Given type VT_UI4 .
iSrc
An int value to copy. Given type VT_INT .
uiSrc
An unsigned int value to copy. Given type VT_UINT .
i8Src
An __int64 or long long value to copy. Given type VT_I8 .
ui8Src
An unsigned __int64 or unsigned long long value to copy. Given type VT_UI8 .
Remarks
The assignment operator clears any existing value, which deletes object types, or calls Release for
operator=
IDispatch* and IUnknown* types. Then, it copies a new value into the _variant_t object. It changes the
_variant_t type to match the assigned value, except as noted for short , long , and double arguments. Value
types are copied directly. A VARIANT or _variant_t pointer or reference argument copies the assigned object's
contents and type. Other pointer or reference type arguments create a copy of the assigned object. The
assignment operator calls AddRef for IDispatch* and IUnknown* arguments.
operator= invokes _com_raise_error if an error occurs.
operator= returns a reference to the updated _variant_t object.
See also
_variant_t class
_variant_t Relational Operators
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Compare two _variant_t objects for equality or inequality.
Syntax
bool operator==(
const VARIANT& varSrc) const;
bool operator==(
const VARIANT* pSrc) const;
bool operator!=(
const VARIANT& varSrc) const;
bool operator!=(
const VARIANT* pSrc) const;
Parameters
varSrc
A VARIANT to be compared with the _variant_t object.
pSrc
Pointer to the VARIANT to be compared with the _variant_t object.
Return Value
Returns true if comparison holds, false if not.
Remarks
Compares a _variant_t object with a VARIANT , testing for equality or inequality.
END Microsoft Specific
See also
_variant_t Class
_variant_t Extractors
3/6/2021 • 2 minutes to read • Edit Online
Microsoft Specific
Extract data from the encapsulated VARIANT object.
Syntax
operator short( ) const;
operator long( ) const;
operator float( ) const;
operator double( ) const;
operator CY( ) const;
operator _bstr_t( ) const;
operator IDispatch*( ) const;
operator bool( ) const;
operator IUnknown*( ) const;
operator DECIMAL( ) const;
operator BYTE( ) const;
operator VARIANT() const throw();
operator char() const;
operator unsigned short() const;
operator unsigned long() const;
operator int() const;
operator unsigned int() const;
operator __int64() const;
operator unsigned __int64() const;
Remarks
Extracts raw data from an encapsulated VARIANT . If the VARIANT is not already the proper type,
VariantChangeType is used to attempt a conversion, and an error is generated upon failure:
See also
_variant_t Class
Microsoft Extensions
3/6/2021 • 2 minutes to read • Edit Online
asm-statement :
__asm assembly-instruction ; opt
__asm { assembly-instruction-list } ; opt
assembly-instruction-list :
assembly-instruction ; opt
assembly-instruction ; assembly-instruction-list ; opt
ms-modifier-list :
ms-modifier ms-modifier-list opt
ms-modifier :
__cdecl
__fastcall
__stdcall
__syscall (reserved for future implementations)
__oldcall (reserved for future implementations)
__unaligned (reserved for future implementations)
based-modifier
based-modifier :
__based ( based-type )
based-type :
name
Nonstandard Behavior
3/6/2021 • 2 minutes to read • Edit Online
The following sections list some of the places where the Microsoft implementation of C++ does not comply with
the C++ standard. The section numbers given below refer to the section numbers in the C++ 11 standard
(ISO/IEC 14882:2011(E)).
The list of compiler limits that differ from those defined in the C++ standard is given in Compiler Limits.
// CovariantReturn.cpp
class A
{
virtual A* f(int c, ...); // remove ...
};
class B : virtual A
{
B* f(int c, ...); // C2688 remove ...
};
#include <iostream>
using namespace std;
namespace N {
void f(int) { cout << "f(int)" << endl;}
}
namespace N {
void f(char) { cout << "f(char)" << endl;}
}
int main() {
g('c');
}
// Output: f(char)
char_traits::eof()
The C++ standard states that char_traits::eof must not correspond to a valid char_type value. The Microsoft
C++ compiler enforces this constraint for type char , but not for type wchar_t . This does not comply with the
requirement in Table 62 in section 12.1.1 of the C++ ISO specification. The example below demonstrates this.
#include <iostream>
int main()
{
using namespace std;
The C++ standard recommends limits for various language constructs. The following is a list of cases where the
Microsoft C++ compiler does not implement the recommended limits. The first number is the limit that is
established in the ISO C++ 11 standard (INCITS/ISO/IEC 14882-2011[2012], Annex B) and the second number
is the limit implemented by the Microsoft C++ compiler:
Nesting levels of compound statements, iteration control structures, and selection control structures -
C++ standard: 256, Microsoft C++ compiler: depends on the combination of statements that are nested,
but generally between 100 and 110.
Parameters in one macro definition - C++ standard: 256, Microsoft C++ compiler: 127.
Arguments in one macro invocation - C++ standard: 256, Microsoft C++ compiler 127.
Characters in a character string literal or wide string literal (after concatenation) - C++ standard: 65536,
Microsoft C++ compiler: 65535 single-byte characters, including the NULL terminator, and 32767
double-byte characters, including the NULL terminator.
Levels of nested class, structure, or union definitions in a single struct-declaration-list - C++ standard:
256, Microsoft C++ compiler: 16.
Member initializers in a constructor definition - C++ standard: 6144, Microsoft C++ compiler: at least
6144.
Scope qualifications of one identifier - C++ standard: 256, Microsoft C++ compiler: 127.
Nested extern specifications - C++ standard: 1024, Microsoft C++ compiler: 9 (not counting the implicit
extern specification in global scope, or 10, if you count the implicit extern specification in global scope..
Template arguments in a template declaration - C++ standard: 1024, Microsoft C++ compiler: 2046.
See also
Nonstandard Behavior
C/C++ preprocessor reference
11/2/2020 • 2 minutes to read • Edit Online
The C/C++ preprocessor reference explains the preprocessor as it is implemented in Microsoft C/C++. The
preprocessor performs preliminary operations on C and C++ files before they are passed to the compiler. You
can use the preprocessor to conditionally compile code, insert files, specify compile-time error messages, and
apply machine-specific rules to sections of code.
In Visual Studio 2019 the /Zc:preprocessor compiler option provides a fully conformant C11 and C17
preprocessor. This is the default when you use the compiler flag /std:c11 or /std:c17 .
In this section
Preprocessor
Provides an overview of the traditional and new conforming preprocessors.
Preprocessor directives
Describes directives, typically used to make source programs easy to change and easy to compile in different
execution environments.
Preprocessor operators
Discusses the four preprocessor-specific operators used in the context of the #define directive.
Predefined macros
Discusses predefined macros as specified by the C and C++ standards and by Microsoft C++.
Pragmas
Discusses pragmas, which offer a way for each compiler to offer machine- and operating system-specific
features while retaining overall compatibility with the C and C++ languages.
Related sections
C++ language reference
Provides reference material for the Microsoft implementation of the C++ language.
C language reference
Provides reference material for the Microsoft implementation of the C language.
C/C++ build reference
Provides links to topics discussing compiler and linker options.
Visual Studio projects - C++
Describes the user interface in Visual Studio that enables you to specify the directories that the project system
will search to locate files for your C++ project.
C++ Standard Library reference
3/9/2021 • 2 minutes to read • Edit Online
A C++ program can call on a large number of functions from this conforming implementation of the C++
Standard Library. These functions perform services such as input and output and provide efficient
implementations of frequently used operations.
For more information about linking with the appropriate Visual C++ runtime .lib file, see C runtime (CRT) and
C++ Standard Library (STL) .lib files.
In this section
C++ Standard Library overview
Provides an overview of the Microsoft implementation of the C++ Standard Library.
iostream Programming
Provides an overview of iostream programming.
Header files reference
Provides links to reference topics about the C++ Standard Library header files, with code examples.