0% found this document useful (0 votes)
58 views110 pages

C++ 15 Lambda Expressions

Uploaded by

btech10253.19
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views110 pages

C++ 15 Lambda Expressions

Uploaded by

btech10253.19
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 110

Lambda expressions in C++

Article • 02/20/2023

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's
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
functions. This article defines what lambdas are, and compares them to other
programming techniques. It describes their advantages, and provides some basic
examples.

Related articles
Lambda expressions vs. function objects
Working with lambda expressions
constexpr lambda expressions

Parts of a lambda expression


Here is a simple lambda that is passed as the third argument to the std::sort()
function:

C++

#include <algorithm>
#include <cmath>

void abssort(float* x, unsigned n) {


std::sort(x, x + n,
// Lambda expression begins
[](float a, float b) {
return (std::abs(a) < std::abs(b));
} // end of lambda expression
);
}

This illustration shows the parts of lambda syntax:


1. capture clause (Also known as the lambda-introducer in the C++ specification.)

2. parameter list Optional. (Also known as the lambda declarator)

3. mutable specification Optional.

4. exception-specification Optional.

5. trailing-return-type Optional.

6. lambda body.

Capture clause
A lambda can introduce new variables in its body (in C++14), and it can also access, or
capture, variables from the surrounding scope. A lambda begins with the capture clause.
It specifies which variables are captured, and whether the capture is by value or by
reference. Variables that have the ampersand ( & ) prefix are accessed by reference and
variables that don't have it are accessed by value.

An empty capture clause, [ ] , indicates that the body of the lambda expression
accesses no variables in the enclosing scope.

You can use a capture-default mode to indicate how to capture any outside variables
referenced in the lambda body: [&] means all variables that you refer to are captured
by reference, and [=] means they're captured by value. You can use a default capture
mode, and then specify the opposite mode explicitly for specific variables. For example,
if a lambda body accesses the external variable total by reference and the external
variable factor by value, then the following capture clauses are equivalent:

C++

[&total, factor]
[factor, &total]
[&, factor]
[=, &total]

Only variables that are mentioned in the lambda body 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 can't appear more than once in a capture clause. The

following code snippet illustrates some examples:

C++

struct S { void f(int i); };

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:

C++

template<class... Args>
void f(Args... args) {
auto x = [args...] { return g(args...); };
x();
}

To use lambda expressions in the body of a class member function, pass the this
pointer to the capture clause to provide access to the member functions and data
members of the enclosing class.

Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): The
this pointer may be captured by value by specifying *this in the capture clause.

Capture by value copies the entire closure to every call site where the lambda is invoked.
(A closure is the anonymous function object that encapsulates the lambda expression.)
Capture by value is useful when the lambda executes in parallel or asynchronous
operations. It's especially useful on certain hardware architectures, such as NUMA.
For an example that shows how to use lambda expressions with class member functions,
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 multi-threading:

Reference captures can be used to modify variables outside, but value captures
can't. ( mutable allows copies to be modified, but not originals.)

Reference captures reflect updates to variables outside, but value captures don't.

Reference captures introduce a lifetime dependency, but value captures have no


lifetime dependencies. It's especially important when the lambda runs
asynchronously. If you capture a local by reference in an async lambda, that local
could easily be gone by the time the lambda runs. Your code could cause 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. This feature lets you capture move-
only variables (such as std::unique_ptr ) from the surrounding scope and use them in a
lambda.

C++

pNums = make_unique<vector<int>>(nums);
//...
auto a = [ptr = move(pNums)]()
{
// use ptr
};

Parameter list
Lambdas can both capture variables and 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.

C++
auto y = [] (int first, int second)
{
return first + second;
};

In C++14, if the parameter type is generic, you can use the auto keyword as the type
specifier. This keyword 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.

C++

auto y = [] (auto first, auto second)


{
return first + second;
};

A lambda expression can take another lambda expression as its argument. For more
information, see "Higher-Order Lambda Expressions" in the article Examples of lambda
expressions.

Because a parameter list is optional, you can omit the empty parentheses if you don't
pass arguments to the lambda expression and its lambda-declarator doesn't 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 doesn't 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
doesn't 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:

C++

// throw_lambda_expression.cpp
// compile with: /W4 /EHsc
int main() // C4297 expected
{
[]() noexcept { throw 5; }();
}

For more information, see Exception specifications (throw).

Return type
The return type of a lambda expression is automatically deduced. You don't have to use
the auto keyword unless you specify a trailing-return-type. The trailing-return-type
resembles the return-type part of an ordinary function or member function. However,
the return type must follow the parameter list, and you must include the trailing-return-
type keyword -> before the return type.

You can omit the return-type part of a lambda expression if the lambda body contains
just one return statement. Or, if the expression doesn't return a value. If the lambda
body contains one return statement, the compiler deduces the return type from the type
of the return expression. Otherwise, the compiler deduces the return type as void .
Consider the following example code snippets that illustrate this principle:

C++

auto x1 = [](int i){ return i; }; // OK: return type is int


auto x2 = []{ return{ 1, 2 }; }; // ERROR: return type is void, deducing
// return type from braced-init-list isn't
valid

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 of a lambda expression is a compound statement. It can contain
anything that's allowed in the body of an ordinary function or member function. 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:

C++

// 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;
}

Output

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.

A lambda expression can only capture variables that have automatic storage duration.
However, 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.

C++

void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;

// The lambda expression that appears in the following call to


// the generate function modifies and uses the local static
// variable nextValue.
generate(v.begin(), v.end(), [] { return nextValue++; });
//WARNING: this isn't thread-safe and is shown for illustration only
}

For more information, see generate.

The following code example uses the function from the previous example, and adds an
example of a lambda expression that uses the C++ Standard Library algorithm
generate_n . This lambda expression assigns an element of a vector object to the sum
of the previous two elements. The mutable keyword is used so that the body of the
lambda expression can modify its copies of the external variables x and y , which the
lambda expression captures by value. Because the lambda expression captures the
original variables x and y by value, their values remain 1 after the lambda executes.

C++

// compile with: /W4 /EHsc


#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

using namespace std;

template <typename C> void print(const string& s, const C& c) {


cout << s;

for (const auto& e : c) {


cout << e << " ";
}

cout << endl;


}

void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;

// The lambda expression that appears in the following call to


// the generate function modifies and uses the local static
// variable nextValue.
generate(v.begin(), v.end(), [] { return nextValue++; });
//WARNING: this isn't thread-safe and is shown for illustration only
}

int main()
{
// The number of elements in the vector.
const int elementCount = 9;
// Create a vector object with each element set to 1.
vector<int> v(elementCount, 1);

// These variables hold the previous two elements of the vector.


int x = 1;
int y = 1;

// Sets each element in the vector to the sum of the


// previous two elements.
generate_n(v.begin() + 2,
elementCount - 2,
[=]() mutable throw() -> int { // lambda is the 3rd parameter
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});
print("vector v after call to generate_n() with lambda: ", v);

// Print the local variables x and y.


// The values of x and y hold their initial values because
// they are captured by value.
cout << "x: " << x << " y: " << y << endl;

// Fill the vector with a sequence of numbers


fillVector(v);
print("vector v after 1st call to fillVector(): ", v);
// Fill the vector with the next sequence of numbers
fillVector(v);
print("vector v after 2nd call to fillVector(): ", v);
}

Output

vector v after call to generate_n() with lambda: 1 1 2 3 5 8 13 21 34


x: 1 y: 1
vector v after 1st call to fillVector(): 1 2 3 4 5 6 7 8 9
vector v after 2nd call to fillVector(): 10 11 12 13 14 15 16 17 18

For more information, see generate_n.

constexpr lambda expressions


Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): You
may declare a lambda expression as constexpr (or use it in a constant expression) when
the initialization of each captured or introduced data member is allowed within a
constant expression.

C++

int y = 32;
auto answer = [y]() constexpr
{
int x = 10;
return y + x;
};

constexpr int Increment(int n)


{
return [n] { return n + 1; }();
}

A lambda is implicitly constexpr if its result satisfies the requirements of a constexpr


function:

C++

auto answer = [](int n)


{
return 32 + n;
};

constexpr int response = answer(10);

If a lambda is implicitly or explicitly constexpr , conversion to a function pointer


produces a constexpr function:

C++

auto Increment = [](int n)


{
return n + 1;
};

constexpr int(*inc)(int) = Increment;

Microsoft-specific
Lambdas aren't supported in the following common language runtime (CLR) managed
entities: ref class , ref struct , value class , or value struct .
If you're using a Microsoft-specific modifier such as __declspec, you can insert it into a
lambda expression immediately after the parameter-declaration-clause . For example:

C++

auto Sqr = [](int t) __declspec(code_seg("PagedMem")) -> int { return t*t;


};

To determine whether a particular modifier is supported by lambdas, see the article


about the modifier in the Microsoft-specific modifiers section.

Visual Studio supports C++11 Standard lambda functionality, and stateless lambdas. A
stateless lambda is convertible to a function pointer that uses an arbitrary calling
convention.

See also
C++ Language Reference
Function Objects in the C++ Standard Library
Function Call
for_each
Lambda Expression Syntax
Article • 08/03/2021

This article demonstrates the syntax and structural elements of lambda expressions. For
a description of lambda expressions, see Lambda Expressions.

Function Objects vs. Lambdas


When you write code, you probably use function pointers and function objects to solve
problems and perform calculations, especially when you use C++ Standard Library
algorithms. Function pointers and function objects each have advantages and
disadvantages—for example, function pointers have minimal syntactic overhead but do
not retain state within a scope, and function objects can maintain state but require the
syntactic overhead of a class definition.

A lambda combines the benefits of function pointers and function objects and avoids
their disadvantages. Like a function object, a lambda is flexible and can maintain state,
but unlike a function object, its compact syntax doesn't require an explicit class
definition. By using lambdas, you can write code that's less cumbersome and less prone
to errors than the code for an equivalent function object.

The following examples compare the use of a lambda to the use of a function object.
The first example uses a lambda to print to the console whether each element in a
vector object is even or odd. The second example uses a function object to accomplish

the same task.

Example 1: Using a Lambda


This example passes a lambda to the for_each function. The lambda prints a result that
states whether each element in a vector object is even or odd.

Code
C++

// even_lambda.cpp
// compile with: cl /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// Create a vector object that contains 9 elements.
vector<int> v;
for (int i = 1; i < 10; ++i) {
v.push_back(i);
}

// Count the number of even numbers in the vector by


// using the for_each function and a lambda.
int evenCount = 0;
for_each(v.begin(), v.end(), [&evenCount] (int n) {
cout << n;
if (n % 2 == 0) {
cout << " is even " << endl;
++evenCount;
} else {
cout << " is odd " << endl;
}
});

// Print the count of even numbers to the console.


cout << "There are " << evenCount
<< " even numbers in the vector." << endl;
}

Output

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.

Example 2: Using a Function Object


Sometimes a lambda would be too unwieldy to extend much further than the previous
example. The next example uses a function object instead of a lambda, together with
the for_each function, to produce the same results as Example 1. Both examples store
the count of even numbers in a vector object. To maintain the state of the operation,
the FunctorClass class stores the m_evenCount variable by reference as a member
variable. To perform the operation, FunctorClass implements the function-call operator,
operator(). The Microsoft C++ compiler generates code that is comparable in size and
performance to the lambda code in Example 1. For a basic problem like the one in this
article, the simpler lambda design is probably better than the function-object design.
However, if you think that the functionality might require significant expansion in the
future, then use a function object design so that code maintenance will be easier.

For more information about the operator(), see Function Call. For more information
about the for_each function, see for_each.

Code
C++

// 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) { }

// The function-call operator prints whether the number is


// even or odd. If the number is even, this method updates
// the counter.
void operator()(int n) const {
cout << n;

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& m_evenCount; // the number of even variables in the vector.


};

int main()
{
// Create a vector object that contains 9 elements.
vector<int> v;
for (int i = 1; i < 10; ++i) {
v.push_back(i);
}

// Count the number of even numbers in the vector by


// using the for_each function and a function object.
int evenCount = 0;
for_each(v.begin(), v.end(), FunctorClass(evenCount));

// Print the count of even numbers to the console.


cout << "There are " << evenCount
<< " even numbers in the vector." << endl;
}

Output

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.

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
Article • 08/17/2021

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 Expressions

Example 1
Because a lambda expression is typed, you can assign it to an auto variable or to a
function object, as shown here:

C++

// declaring_lambda_expressions1.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{

using namespace std;

// Assign the lambda expression that adds two numbers to an auto


variable.
auto f1 = [](int x, int y) { return x + y; };

cout << f1(2, 3) << endl;

// Assign the same lambda expression to a function object.


function<int(int, int)> f2 = [](int x, int y) { return x + y; };

cout << f2(3, 4) << endl;


}

The example produces this output:

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.

C++

// declaring_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{
using namespace std;

int i = 3;
int j = 5;

// The following lambda expression captures i by value and


// j by reference.
function<int (void)> f = [i, &j] { return i + j; };

// Change the values of i and j.


i = 22;
j = 44;

// Call f and print its result.


cout << f() << endl;
}

The example produces this output:

Output
47

[In This Article]

Calling Lambda Expressions


You can call a lambda expression immediately, as shown in the next code snippet. The
second snippet shows how to pass a lambda as an argument to C++ Standard Library
algorithms such as find_if .

Example 1
This example declares a lambda expression that returns the sum of two integers and
calls the expression immediately with the arguments 5 and 4 :

C++

// 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;
}

The example produces this output:

Output

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.

C++

// calling_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <list>
#include <algorithm>
#include <iostream>

int main()
{
using namespace std;

// Create a list of integers with a few initial elements.


list<int> numbers;
numbers.push_back(13);
numbers.push_back(17);
numbers.push_back(42);
numbers.push_back(46);
numbers.push_back(99);

// Use the find_if function and a lambda expression to find the


// first even number in the list.
const list<int>::const_iterator result =
find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) ==
0; });

// Print the result.


if (result != numbers.end()) {
cout << "The first even number in the list is " << *result << "." <<
endl;
} else {
cout << "The list contains no even numbers." << endl;
}
}

The example produces this output:

Output

The first even number in the list is 42.

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]

Nesting Lambda Expressions


Example
You can nest a lambda expression inside another one, as shown in this example. The
inner lambda expression multiplies its argument by 2 and returns the result. The outer
lambda expression calls the inner lambda expression with its argument and adds 3 to
the result.

C++

// nesting_lambda_expressions.cpp
// compile with: /EHsc /W4
#include <iostream>

int main()
{
using namespace std;

// The following lambda expression contains a nested lambda


// expression.
int timestwoplusthree = [](int x) { return [](int y) { return y * 2; }
(x) + 3; }(5);

// Print the result.


cout << timestwoplusthree << endl;
}

The example produces this output:

Output

13

Remarks
In this example, [](int y) { return y * 2; } is the nested lambda expression.

[In This Article]

Higher-Order Lambda Functions

Example
Many programming languages support the concept of a higher-order function. A higher-
order function is a lambda expression that takes another lambda expression as its
argument or returns a lambda expression. You can use the function class to enable a
C++ lambda expression to behave like a higher-order function. The following example
shows a lambda expression that returns a function object and a lambda expression that
takes a function object as its argument.

C++

// higher_order_lambda_expression.cpp
// compile with: /EHsc /W4
#include <iostream>
#include <functional>

int main()
{
using namespace std;

// The following code declares a lambda expression that returns


// another lambda expression that adds two numbers.
// The returned lambda expression captures parameter x by value.
auto addtwointegers = [](int x) -> function<int(int)> {
return [=](int y) { return x + y; };
};

// The following code declares a lambda expression that takes another


// lambda expression as its argument.
// The lambda expression applies the argument z to the function f
// and multiplies by 2.
auto higherorder = [](const function<int(int)>& f, int z) {
return f(z) * 2;
};

// Call the lambda expression that is bound to higherorder.


auto answer = higherorder(addtwointegers(7), 8);

// Print the result, which is (7+8)*2.


cout << answer << endl;
}

The example produces this output:

Output

30

[In This Article]

Using a Lambda Expression in a Function


Example
You can use lambda expressions in the body of a function. The lambda expression can
access any function or data member that the enclosing function can access. You can
explicitly or implicitly capture the this pointer to provide access to functions and data
members of the enclosing class. Visual Studio 2017 version 15.3 and later (Available
with /std:c++17 and later): Capture this by value ( [*this] ) when the lambda will be
used in asynchronous or parallel operations where the code might execute after the
original object goes out of scope.

You can use the this pointer explicitly in a function, as shown here:

C++

// capture "this" by reference


void ApplyScale(const vector<int>& v) const
{
for_each(v.begin(), v.end(),
[this](int n) { cout << n * _scale << endl; });
}

// 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; });
}

You can also capture the this pointer implicitly:

C++

void ApplyScale(const vector<int>& v) const


{
for_each(v.begin(), v.end(),
[=](int n) { cout << n * _scale << endl; });
}

The following example shows the Scale class, which encapsulates a scale value.

C++

// function_lambda_expression.cpp
// compile with: /EHsc /W4
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class Scale
{
public:
// The constructor.
explicit Scale(int scale) : _scale(scale) {}

// Prints the product of each element in a vector object


// and the scale value to the console.
void ApplyScale(const vector<int>& v) const
{
for_each(v.begin(), v.end(), [=](int n) { cout << n * _scale <<
endl; });
}

private:
int _scale;
};

int main()
{
vector<int> values;
values.push_back(1);
values.push_back(2);
values.push_back(3);
values.push_back(4);

// Create a Scale object that scales elements by 3 and apply


// it to the vector object. Does not modify the vector.
Scale s(3);
s.ApplyScale(values);
}

The example produces this output:

Output

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.
[In This Article]

Using Lambda Expressions with Templates

Example
Because lambda expressions are typed, you can use them with C++ templates. The
following example shows the negate_all and print_all functions. The negate_all
function applies the unary operator- to each element in the vector object. The
print_all function prints each element in the vector object to the console.

C++

// template_lambda_expression.cpp
// compile with: /EHsc
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

// 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; });
}

// Prints to the console each element in the vector object.


template <typename T>
void print_all(const vector<T>& v)
{
for_each(v.begin(), v.end(), [](const T& n) { cout << n << endl; });
}

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);
}
The example produces this output:

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.

C++

// 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);

// Create another vector that contains index values.


vector<int> indices(3);
indices[0] = 0;
indices[1] = -1; // This is not a valid subscript. It will trigger an
exception.
indices[2] = 2;

// Use the values from the vector of index values to


// fill the elements vector. This example uses a
// try/catch block to handle invalid access to the
// elements vector.
try
{
for_each(indices.begin(), indices.end(), [&](int index) {
elements.at(index) = index;
});
}
catch (const out_of_range& e)
{
cerr << "Caught '" << e.what() << "'." << endl;
};
}

The example produces this output:

Output

Caught 'invalid vector<T> subscript'.

Remarks
For more information about exception handling, see Exception Handling.

[In This Article]

Using Lambda Expressions with Managed


Types (C++/CLI)

Example
The capture clause of a lambda expression cannot contain a variable that has a
managed type. However, you can pass an argument that has a managed type to the
parameter list of a lambda expression. The following example contains a lambda
expression that captures the local unmanaged variable ch by value and takes a
System.String object as its parameter.

C++
// managed_lambda_expression.cpp
// compile with: /clr
using namespace System;

int main()
{
char ch = '!'; // a local unmanaged variable

// The following lambda expression captures local variables


// by value and takes a managed String object as its parameter.
[=](String ^s) {
Console::WriteLine(s + Convert::ToChar(ch));
}("Hello");
}

The example produces this output:

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 .

[In This Article]

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++
Article • 08/17/2021

Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): 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.

C++

int y = 32;
auto answer = [y]() constexpr
{
int x = 10;
return y + x;
};

constexpr int Increment(int n)


{
return [n] { return n + 1; }();
}

A lambda is implicitly constexpr if its result satisfies the requirements of a constexpr


function:

C++

auto answer = [](int n)


{
return 32 + n;
};

constexpr int response = answer(10);

If a lambda is implicitly or explicitly constexpr , and you convert it to a function pointer,


the resulting function is also constexpr :

C++

auto Increment = [](int n)


{
return n + 1;
};

constexpr int(*inc)(int) = Increment;


See also
C++ Language Reference
Function Objects in the C++ Standard Library
Function Call
for_each
Arrays (C++)
Article • 02/14/2023

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 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.

C++

constexpr size_t size = 1000;

// Declare an array of doubles to be allocated on the stack


double numbers[size] {0};

// Assign a new value to the first element


numbers[0] = 1;

// Assign a value to each subsequent element


// (numbers[1] is the second element in the array.)
for (size_t i = 1; i < size; i++)
{
numbers[i] = numbers[i-1] * 1.1;
}

// Access each element


for (size_t i = 0; i < size; i++)
{
std::cout << numbers[i] << " ";
}
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:

C++

void do_something(size_t size)


{
// Declare an array of doubles to be allocated on the heap
double* numbers = new double[size]{ 0 };

// Assign a new value to the first element


numbers[0] = 1;

// Assign a value to each subsequent element


// (numbers[1] is the second element in the array.)
for (size_t i = 1; i < size; i++)
{
numbers[i] = numbers[i - 1] * 1.1;
}

// Access each element with subscript operator


for (size_t i = 0; i < size; i++)
{
std::cout << numbers[i] << " ";
}

// Access each element with pointer arithmetic


// Use a copy of the pointer for iterating
double* p = numbers;

for (size_t i = 0; i < size; i++)


{
// Dereference the pointer, then increment it
std::cout << *p++ << " ";
}

// Alternate method:
// Reset p to numbers[0]:
p = numbers;

// Use address of pointer to compute bounds.


// The compiler computes size as the number
// of elements * (bytes per element).
while (p < (numbers + size))
{
// Dereference the pointer, then increment it
std::cout << *p++ << " ";
}

delete[] numbers; // don't forget to do this!

}
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:

C++

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 };

Passing arrays to functions


When an array is passed to a function, it's passed as a pointer to the first element,
whether it's a stack-based or heap-based array. The pointer contains no other size or
type information. This behavior is called pointer decay. When you pass an array to a
function, you must always specify the number of elements in a separate parameter. This
behavior also implies that the array elements aren't copied when the array gets passed
to a function. To prevent the function from modifying the elements, specify the
parameter as a pointer to const elements.

The following example shows a function that accepts an array and a length. The pointer
points to the original array, not a copy. Because the parameter isn't const , the function
can modify the array elements.

C++

void process(double *p, const size_t len)


{
std::cout << "process:\n";
for (size_t i = 0; i < len; ++i)
{
// do something with p[i]
}
}

Declare and define the array parameter p as const to make it read-only within the
function block:

C++

void process(const double *p, const size_t len);

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:

C++

// Unsized array
void process(const double p[], const size_t len);
// Fixed-size array. Length must still be specified explicitly.
void process(const double p[1000], 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:

C++

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:

The image is a grid 7 cells wide and 5 cells high. Each cell contains the index of the cell.
The first cell index is labeled 0,0. The next cell in that row is 0,1 and so on to the last cell
in that row which is 0,6. The next row starts with the index 1,0. The cell after that has an
index of 1,1. The last cell in that row is 1,6. This pattern repeats until the last row, which
starts with the index 4,0. The the last cell in the last row has an index of 4,6. :::image-end

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:

C++

// 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:

C++

// multidimensional_arrays.cpp
// compile with: /EHsc
// arguments: 3
#include <limits> // Includes DBL_MAX
#include <iostream>

const int cMkts = 4, cFacts = 2;

// Declare a float that represents the transportation costs


double TransportCosts[][cMkts] = {
{ 32.19, 47.29, 31.99, 19.11 },
{ 11.29, 22.49, 33.47, 17.29 },
{ 41.97, 22.09, 9.76, 22.55 }
};

// Calculate size of unspecified dimension


const int cFactories = sizeof TransportCosts /
sizeof( double[cMkts] );

double FindMinToMkt( int Mkt, double myTransportCosts[][cMkts], int


mycFacts);

using namespace std;

int main( int argc, char *argv[] ) {


double MinCost;

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";
}

double FindMinToMkt(int Mkt, double myTransportCosts[][cMkts], int mycFacts)


{
double MinCost = DBL_MAX;

for( size_t i = 0; i < cFacts; ++i )


MinCost = (MinCost < TransportCosts[i][Mkt]) ?
MinCost : TransportCosts[i][Mkt];

return MinCost;
}

Output

The minimum cost to Market 3 is: 17.29

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:

C++

// initializing_arrays1.cpp
class Point
{
public:
Point() // Default constructor.
{
}
Point( int, int ) // Construct from two ints
{
}
};

// An array of Point objects can be declared as follows:


Point aPoint[3] = {
Point( 3, 3 ) // Use int, int constructor.
};

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:

C++

// initializing_arrays2.cpp
class WindowColors
{
public:
static const char *rgszWindowPartList[7];
};

const char *WindowColors::rgszWindowPartList[7] = {


"Active Title Bar", "Inactive Title Bar", "Title Bar Text",
"Menu Bar", "Menu Bar Text", "Window Background", "Frame" };
int main()
{
}

Accessing array elements


You can access individual elements of an array by using the array subscript operator ( [
] ). If you use the name of a one-dimensional array without a subscript, it gets evaluated

as a pointer to the array's first element.

C++

// 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.

C++

// 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);

cout << multi[3][2][2] << "\n"; // C4700 Use three subscripts.


p2multi = multi[3]; // Make p2multi point to
// fourth "plane" of multi.
p1multi = multi[3][2]; // Make p1multi point to
// fourth plane, third row
// of multi.
}

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 .

Overloading subscript operator


Like other operators, the subscript operator ( [] ) can be redefined by the user. The
default behavior of the subscript operator, if not overloaded, is to combine the array
name and the subscript using the following method:

*((array_name) + (subscript))

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:

C++

char szError1[] = "Error: Disk drive not ready.";


char *psz = szError1;

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:

C++

szError1 = psz;

See also
std::array
References (C++)
Article • 03/25/2024

A reference, like a pointer, stores the address of an object that is located elsewhere in
memory. Unlike a pointer, a reference after it's initialized can't 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:

[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] declarator [ =


expression] ;

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:

[storage-class-specifiers] [cv-qualifiers] type-specifiers [ & or && ] [cv-qualifiers]


identifier [ = expression] ;

References are declared using the following sequence:

1. The declaration specifiers:

An optional storage class specifier.


Optional const and/or volatile qualifiers.
The type specifier: the name of a type.

2. The declarator:

An optional Microsoft-specific modifier. For more information, see Microsoft-


Specific Modifiers.

The & operator or && operator.

Optional const and/or volatile qualifers.

The identifier.

3. An optional initializer.
The more complex declarator forms for pointers to arrays and functions also apply to
references to arrays and functions. For more information, see pointers.

Multiple declarators and initializers may appear in a comma-separated list following a


single declaration specifier. For example:

C++

int &i;
int &i, &j;

References, pointers, and objects may be declared together:

C++

int &ref, *ptr, k;

A reference holds the address of an object, but behaves syntactically like an object.

In the following program, notice that the name of the object, s , and the reference to
the object, SRef , can be used identically in programs:

Example
C++

// references.cpp
#include <stdio.h>
struct S {
short i;
};

int main() {
S s; // Declare the object.
S& SRef = s; // Declare and initialize 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);
}

Output
3
3
4
4

See also
Reference-Type Function Arguments
Reference-Type Function Returns
References to Pointers

Feedback
Was this page helpful?  Yes  No

Provide product feedback | Get help at Microsoft Q&A


Lvalue reference declarator: &
Article • 11/23/2021

Holds the address of an object but behaves syntactically like an object.

Syntax
lvalue-reference-type-id :

type-specifier-seq & attribute-specifier-seq opt ptr-abstract-declarator opt

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 & .

Don't 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.

C++

// 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;

// Declare a reference to the Person object.


Person& rFriend = myFriend;

// Set the fields of the Person object.


// Updating either variable changes the same object.
myFriend.Name = "Bill";
rFriend.Age = 40;

// Print the fields of the Person object to the console.


cout << rFriend.Name << " is " << myFriend.Age << endl;
}

Output

Bill is 40

See also
References
Reference-type function arguments
Reference-type function returns
References to pointers
Rvalue reference declarator: &&
Article • 09/28/2022

Holds a reference to an rvalue expression.

Syntax
rvalue-reference-type-id :

type-specifier-seq && attribute-specifier-seq opt ptr-abstract-declarator opt

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 slightly
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 transfer of resources from
temporary objects: ones that can't 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 doesn't provide a default move constructor.
For more information about how to write and use a move constructor, see Move
constructors and move assignment operators.

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 use move semantics.
Consider the following example that concatenates several strings and prints the result:
C++

// 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+ can't append one string to the other because it

doesn't 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 so must not be
modified. You can modify operator+ to take rvalues by using rvalue references, which
can't be referenced elsewhere in the program. With this change, operator+ can now
append one string to another. The change significantly reduces the number of dynamic
memory allocations that the string class must make. For more information about the
string class, see basic_string Class.

Move semantics also helps when the compiler can't 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 enough 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 first creates a new element. Then it calls the copy
constructor to copy the data from the previous element to the new element. Finally, it
destroys the previous element. Move semantics enables you to move objects directly
without having to make 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. If it passes (or forwards) these
parameters to another function, for example, if it takes a parameter of type const T& ,
then the called function can't modify the value of that parameter. If the generic function
takes a parameter of type T& , then the function can't 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. Then that function can forward 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.

C++

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:
C++

template <typename T, typename A1, typename A2>


T* factory(A1& a1, A2& a2)
{
return new T(a1, a2);
}

The following example shows a valid call to the factory function:

C++

int a = 4, b = 5;
W* pw = factory<W>(a, b);

However, the following example doesn't contain a valid call to the factory function. It's
because factory takes lvalue references that are modifiable as its parameters, but it's
called by using rvalues:

C++

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:

C++

template <typename T, typename A1, typename A2>


T* factory(A1&& a1, A2&& a2)
{
return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}

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.
C++

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;
}

Properties of rvalue references


You can overload a function to take an lvalue reference and an rvalue reference.

By overloading a function to take a const lvalue reference or an rvalue reference, you


can write code that distinguishes between non-modifiable objects (lvalues) and
modifiable temporary values (rvalues). You can pass an object to a function that takes an
rvalue reference unless the object is marked as const . The following example shows the
function f , which is overloaded to take an lvalue reference and an rvalue reference. The
main function calls f with both lvalues and an rvalue.

C++

// reference-overload.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;

// A class that contains a memory resource.


class MemoryBlock
{
// TODO: Add resources for the class here.
};

void f(const MemoryBlock&)


{
cout << "In f(const MemoryBlock&). This version can't modify the
parameter." << endl;
}

void f(MemoryBlock&&)
{
cout << "In f(MemoryBlock&&). This version can modify the parameter." <<
endl;
}

int main()
{
MemoryBlock block;
f(block);
f(MemoryBlock());
}

This example produces the following output:

Output

In f(const MemoryBlock&). This version can't modify the parameter.


In f(MemoryBlock&&). This version can modify the parameter.

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 can't 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 rvalue reference as an lvalue and an unnamed rvalue
reference as an rvalue.

Functions that take an rvalue reference as a parameter treat the parameter as an lvalue
in the body of the function. The compiler treats a named rvalue reference as an lvalue.
It's because a named object can be referenced by several parts of a program. It's
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 transfer succeeds.

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.

C++

// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;

// A class that contains a memory resource.


class MemoryBlock
{
// TODO: Add resources for the class here.
};

void g(const MemoryBlock&)


{
cout << "In g(const MemoryBlock&)." << endl;
}

void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}

MemoryBlock&& f(MemoryBlock&& block)


{
g(block);
return move(block);
}

int main()
{
g(f(MemoryBlock()));
}

This example produces the following output:

C++

In g(const MemoryBlock&).
In g(MemoryBlock&&).

In the 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 rvalue reference.

The C++ Standard Library std::move function enables you to convert an object to an
rvalue reference to that object. You can also use the static_cast keyword to cast an
lvalue to an rvalue reference, as shown in the following example:

C++
// cast-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;

// A class that contains a memory resource.


class MemoryBlock
{
// TODO: Add resources for the class here.
};

void g(const MemoryBlock&)


{
cout << "In g(const MemoryBlock&)." << endl;
}

void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}

int main()
{
MemoryBlock block;
g(block);
g(static_cast<MemoryBlock&&>(block));
}

This example produces the following output:

C++

In g(const MemoryBlock&).
In g(MemoryBlock&&).

Function templates deduce their template argument types and then use reference
collapsing rules.

A function template that passes (or forwards) its parameters to another function is a
common pattern. It's 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, assume you pass an rvalue reference to an object of type
X to a function template that takes type T&& as its parameter. Template argument

deduction deduces T to be X , so 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.

C++

// template-type-deduction.cpp
// Compile with: /EHsc
#include <iostream>
#include <string>
using namespace std;

template<typename T> struct S;

// The following structures specialize S by


// lvalue reference (T&), const lvalue reference (const T&),
// rvalue reference (T&&), and const rvalue reference (const T&&).
// Each structure provides a print method that prints the type of
// the structure and its parameter.

template<typename T> struct S<T&> {


static void print(T& t)
{
cout << "print<T&>: " << t << endl;
}
};

template<typename T> struct S<const T&> {


static void print(const T& t)
{
cout << "print<const T&>: " << t << endl;
}
};

template<typename T> struct S<T&&> {


static void print(T&& t)
{
cout << "print<T&&>: " << t << endl;
}
};

template<typename T> struct S<const T&&> {


static void print(const T&& t)
{
cout << "print<const T&&>: " << t << endl;
}
};

// This function forwards its parameter to a specialized


// version of the S type.
template <typename T> void print_type_and_value(T&& t)
{
S<T&&>::print(std::forward<T>(t));
}

// This function returns the constant string "fourth".


const string fourth() { return string("fourth"); }

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);

// The following call resolves to:


// print_type_and_value<const string&>(const string& && t)
// Which collapses to:
// print_type_and_value<const string&>(const string& t)
const string s2("second");
print_type_and_value(s2);

// The following call resolves to:


// print_type_and_value<string&&>(string&& t)
print_type_and_value(string("third"));

// The following call resolves to:


// print_type_and_value<const string&&>(const string&& t)
print_type_and_value(fourth());
}

This example produces the following output:

C++

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 does
template argument deduction. The compiler then applies reference collapsing rules
when it replaces the parameter types with the deduced template arguments. For
example, passing the local variable s1 to the print_type_and_value function causes the
compiler to produce the following function signature:

C++

print_type_and_value<string&>(string& && t)
The compiler uses reference collapsing rules to reduce the signature:

C++

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:

Expanded type Collapsed type

T& & T&

T& && T&

T&& & T&

T&& && T&&

Template argument deduction is an important element of implementing perfect


forwarding. The Perfect forwarding section describes perfect forwarding in more detail.

Summary
Rvalue references distinguish lvalues from rvalues. To improve the performance of your
applications, they can eliminate the need for unnecessary memory allocations and copy
operations. They also enable you to write a function that accepts arbitrary arguments.
That function can forward 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
Article • 08/03/2021

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:

C++

// reference_type_function_arguments.cpp
#include <iostream>

struct Date
{
short Month;
short Day;
short Year;
};

// Create a date of the form DDDYYYY (day of year, year)


// from a Date.
long DateOfYear( Date& date )
{
static int cDaysInMonth[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
long dateOfYear = 0;

// Add in days for months already elapsed.


for ( int i = 0; i < date.Month - 1; ++i )
dateOfYear += cDaysInMonth[i];

// Add in days for this month.


dateOfYear += date.Day;

// Check for leap year.


if ( date.Month > 2 &&
(( date.Year % 100 != 0 || date.Year % 400 == 0 ) &&
date.Year % 4 == 0 ))
dateOfYear++;

// 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:

C++

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
Article • 10/17/2022

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:

C++

// 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;
};
unsigned& Point :: x()
{
return obj_x;
}
unsigned& Point :: y()
{
return obj_y;
}

int main()
{
Point ThePoint;
// Use x() and y() as l-values.
ThePoint.x() = 7;
ThePoint.y() = 9;

// Use x() and y() as r-values.


cout << "x = " << ThePoint.x() << "\n"
<< "y = " << ThePoint.y() << "\n";
}

Output
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.

C++

// C4172 means Don't do this!!!


Foo& GetFoo()
{
Foo f;
...
return f;
} // f is destroyed here

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
Article • 08/03/2021

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.

C++

// references_to_pointers.cpp
// compile with: /EHsc

#include <iostream>
#include <string>

// C++ Standard Library namespace


using namespace std;

enum {
sizeOfBuffer = 132
};

// Define a binary tree structure.


struct BTree {
char *szText;
BTree *Left;
BTree *Right;
};

// Define a pointer to the root of the tree.


BTree *btRoot = 0;

int Add1( BTree **Root, char *szToAdd );


int Add2( BTree*& Root, char *szToAdd );
void PrintTree( BTree* btRoot );

int main( int argc, char *argv[] ) {


// Usage message
if( argc < 2 ) {
cerr << "Usage: " << argv[0] << " [1 | 2]" << "\n";
cerr << "\nwhere:\n";
cerr << "1 uses double indirection\n";
cerr << "2 uses a reference to a pointer.\n";
cerr << "\nInput is from stdin. Use ^Z to terminate input.\n";
return 1;
}

char *szBuf = new char[sizeOfBuffer];


if (szBuf == NULL) {
cerr << "Out of memory!\n";
return -1;
}

// Read a text file from the standard input device and


// build a binary tree.
while( !cin.eof() )
{
cin.get( szBuf, sizeOfBuffer, '\n' );
cin.get();

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 );
}

// PrintTree: Display the binary tree in order.


void PrintTree( BTree* MybtRoot ) {
// Traverse the left branch of the tree recursively.
if ( MybtRoot->Left )
PrintTree( MybtRoot->Left );

// Print the current node.


cout << MybtRoot->szText << "\n";

// Traverse the right branch of the tree recursively.


if ( MybtRoot->Right )
PrintTree( MybtRoot->Right );
}

// Add1: Add a node to the binary tree.


// Uses double indirection.
int Add1( BTree **Root, char *szToAdd ) {
if ( (*Root) == 0 ) {
(*Root) = new BTree;
(*Root)->Left = 0;
(*Root)->Right = 0;
(*Root)->szText = new char[strlen( szToAdd ) + 1];
strcpy_s((*Root)->szText, (strlen( szToAdd ) + 1), szToAdd );
return 1;
}
else {
if ( strcmp( (*Root)->szText, szToAdd ) > 0 )
return Add1( &((*Root)->Left), szToAdd );
else
return Add1( &((*Root)->Right), szToAdd );
}
}

// Add2: Add a node to the binary tree.


// Uses reference to pointer
int Add2( BTree*& Root, char *szToAdd ) {
if ( Root == 0 ) {
Root = new BTree;
Root->Left = 0;
Root->Right = 0;
Root->szText = new char[strlen( szToAdd ) + 1];
strcpy_s( Root->szText, (strlen( szToAdd ) + 1), szToAdd );
return 1;
}
else {
if ( strcmp( Root->szText, szToAdd ) > 0 )
return Add2( Root->Left, szToAdd );
else
return Add2( Root->Right, szToAdd );
}
}

Output

Usage: references_to_pointers.exe [1 | 2]

where:
1 uses double indirection
2 uses a reference to a pointer.

Input is from stdin. Use ^Z to terminate input.

See also
References
Pointers (C++)
Article • 08/03/2021

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++)
Article • 11/07/2022

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 isn't 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.

C++

int* p = nullptr; // declare pointer and initialize it


// so that it doesn't store a random address
int i = 5;
p = &i; // assign pointer to address of object
int j = *p; // dereference p to retrieve the value at its address

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.

C++

MyClass* mc = new MyClass(); // allocate object on the heap


mc->print(); // access class member
delete mc; // delete object (please don't forget!)

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.

C++
// declare a C-style string. Compiler adds terminating '\0'.
const char* str = "Hello world";

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. 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. They're used for
"callbacks" in C-style programming. Modern C++ uses lambda expressions for this
purpose.

Initialization and member access


The following example shows how to declare, initialize, and use a raw pointer. It's
initialized using new to point an object allocated on the heap, which you must explicitly
delete . The example also shows a few of the dangers associated with raw pointers.
(Remember, this example is C-style programming and not modern C++!)

C++

#include <iostream>
#include <string>

class MyClass
{
public:
int num;
std::string name;
void print() { std::cout << name << ":" << num << std::endl; }
};

// Accepts a MyClass pointer


void func_A(MyClass* mc)
{
// Modify the object that mc points to.
// All copies of the pointer will point to
// the same modified object.
mc->num = 3;
}

// Accepts a MyClass object


void func_B(MyClass mc)
{
// mc here is a regular object, not a pointer.
// Use the "." operator to access members.
// This statement modifies only the local copy of mc.
mc.num = 21;
std::cout << "Local copy of mc:";
mc.print(); // "Erika, 21"
}

int main()
{
// Use the * operator to declare a pointer type
// Use new to allocate and initialize memory
MyClass* pmc = new MyClass{ 108, "Nick" };

// Prints the memory address. Usually not what you want.


std:: cout << pmc << std::endl;

// Copy the pointed-to object by dereferencing the pointer


// to access the contents of the memory location.
// mc is a separate object, allocated here on the stack
MyClass mc = *pmc;

// Declare a pointer that points to mc using the addressof operator


MyClass* pcopy = &mc;

// Use the -> operator to access the object's public members


pmc->print(); // "Nick, 108"

// Copy the pointer. Now pmc and pmc2 point to same object!
MyClass* pmc2 = pmc;

// Use copied pointer to modify the original object


pmc2->name = "Erika";
pmc->print(); // "Erika, 108"
pmc2->print(); // "Erika, 108"

// Pass the pointer to a function.


func_A(pmc);
pmc->print(); // "Erika, 3"
pmc2->print(); // "Erika, 3"

// Dereference the pointer and pass a copy


// of the pointed-to object to a function
func_B(*pmc);
pmc->print(); // "Erika, 3" (original not modified by function)
delete(pmc); // don't forget to give memory back to operating system!
// delete(pmc2); //crash! memory location was already deleted
}

Pointer arithmetic and arrays


Pointers and arrays are closely related. When an array is passed by-value to a function,
it's passed as a pointer to the first element. The following example demonstrates the
following important properties of pointers and arrays:

The sizeof operator returns the total size in bytes of an array


To determine the number of elements, divide total bytes by the size of one
element
When an array is passed to a function, it decays to a pointer type
When the sizeof operator is applied to a pointer, it returns the pointer size, for
example, 4 bytes on x86 or 8 bytes on x64

C++

#include <iostream>

void func(int arr[], int length)


{
// returns pointer size. not useful here.
size_t test = sizeof(arr);

for(int i = 0; i < length; ++i)


{
std::cout << arr[i] << " ";
}
}

int main()
{

int i[5]{ 1,2,3,4,5 };


// sizeof(i) = total bytes
int j = sizeof(i) / sizeof(i[0]);
func(i,j);
}

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.

C++

#include <Windows.h>
#include <fstream>

using namespace std;

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);

constexpr int bufferSize = 30000;


unsigned char* buffer = new unsigned char[bufferSize];

BITMAPFILEHEADER bf;
bf.bfType = 0x4D42;
bf.bfSize = header.biSize + 14 + bufferSize;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //54

// Create a gray square with a 2-pixel wide outline.


unsigned char* begin = &buffer[0];
unsigned char* end = &buffer[0] + bufferSize;
unsigned char* p = begin;
constexpr int pixelWidth = 3;
constexpr int borderWidth = 2;

while (p < end)


{
// Is top or bottom edge?
if ((p < begin + header.biWidth * pixelWidth * borderWidth)
|| (p > end - header.biWidth * pixelWidth * borderWidth)
// Is left or right edge?
|| (p - begin) % (header.biWidth * pixelWidth) < (borderWidth *
pixelWidth)
|| (p - begin) % (header.biWidth * pixelWidth) >
((header.biWidth - borderWidth) * pixelWidth))
{
*p = 0x0; // Black
}
else
{
*p = 0xC3; // Gray
}
p++; // Increment one byte sizeof(unsigned char).
}

ofstream wf(R"(box.bmp)", ios::out | ios::binary);

wf.write(reinterpret_cast<char*>(&bf), sizeof(bf));
wf.write(reinterpret_cast<char*>(&header), sizeof(header));
wf.write(reinterpret_cast<char*>(begin), bufferSize);

delete[] buffer; // Return memory to the OS.


wf.close();
}

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.

C++

//func.c
void func(void* data, int length)
{
char* c = (char*)(data);

// fill in the buffer with data


for (int i = 0; i < length; ++i)
{
*c = 0x41;
++c;
}
}

// 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"
delete(mc);

// use operator new to allocate untyped memory block


void* pvoid = operator new(1000);
char* pchar = static_cast<char*>(pvoid);
for(char* c = pchar; c < pchar + 1000; ++c)
{
*c = 0x00;
}
func(pvoid, 1000);
char ch = static_cast<char*>(pvoid)[0];
std::cout << ch << std::endl; // 'A'
operator delete(pvoid);
}

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:

C++

// Declare pointer to any function that...

// ...accepts a string and returns a string


string (*g)(string a);
// has no return value and no parameters
void (*x)();

// ...returns an int and takes three parameters


// of the specified types
int (*i)(int i, string s, double d);

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.

C++

#include <iostream>
#include <string>

using namespace std;

string base {"hello world"};

string append(string s)
{
return base.append(" ").append(s);
}

string prepend(string s)
{
return s.append(" ").append(base);
}

string combine(string s, string(*g)(string a))


{
return (*g)(s);
}

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
Article • 08/03/2021

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:

C++

const char *cpch;


volatile char *vpch;

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:

C++

char * const pchc;


char * volatile pchv;

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:

C++
const char cch = 'A';
char ch = 'B';

Given the preceding declarations of two objects ( cch , of type const char, and ch , of
type char), the following declaration/initializations are valid:

C++

const char *pch1 = &cch;


const char *const pch4 = &cch;
const char *pch5 = &ch;
char *pch6 = &ch;
char *const pch7 = &ch;
const char *const pch8 = &ch;

The following declaration/initializations are erroneous.

C++

char *pch2 = &cch; // Error


char *const pch3 = &cch; // Error

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 .

C++

*pch1 = 'A'; // Error: object declared const


pch1 = &ch; // OK: pointer not declared const
*pch2 = 'A'; // OK: normal pointer
pch2 = &ch; // OK: normal pointer
*pch3 = 'A'; // OK: object not declared const
pch3 = &ch; // Error: pointer declared const
*pch4 = 'A'; // Error: object declared const
pch4 = &ch; // Error: pointer declared const

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:

C++

errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char


*strSource );

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.

7 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:

C++

// 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.

C++

// 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
Article • 05/30/2022

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
(also known as the heap). The new operator calls the special function operator new, and
the delete operator calls the special function operator delete.

For a list of the library files in the C Runtime Library and the C++ Standard Library, see
CRT Library Features.

The new operator


The compiler translates a statement such as this one into a call to the function operator
new :

C++

char *pch = new char[BUFFER_SIZE];

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 used the placement form

new(std::nothrow) , or if you've linked in non-throwing operator new support. For more

information, see Allocation failure behavior.

The two scopes for operator new functions are described in the following table.

Scope for operator new functions

Operator Scope

::operator new Global

class-name ::operator new Class

The first argument of operator new must be of type size_t , 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:

C++

#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:

C++

Blanks *SomeBlanks = new Blanks;

The compiler supports member array new and delete operators in a class declaration.
For example:
C++

class MyClass
{
public:
void * operator new[] (size_t)
{
return 0;
}
void operator delete[] (void*)
{
}
};

int main()
{
MyClass *pMyClass = new MyClass[5];
delete [] pMyClass;
}

Allocation failure behavior


The new function in the C++ Standard Library supports the behavior specified in the
C++ standard since C++98. When there's insufficient memory for an allocation request,
operator new throws a std::bad_alloc exception.

Older C++ code returned a null pointer for a failed allocation. If you have code that
expects the non-throwing version of new , link your program with nothrownew.obj . The
nothrownew.obj file replaces global operator new with a version that returns nullptr if

an allocation fails. operator new no longer throws std::bad_alloc . For more information
about nothrownew.obj and other linker option files, see Link options.

You can't mix code that checks for exceptions from global operator new with code that
checks for null pointers in the same application. However, you can still create class-local
operator new that behaves differently. This possibility means the compiler must act

defensively by default and include checks for null pointer returns in new calls. For more
information on a way to optimize these compiler checks, see /Zc:throwingnew.

Handling insufficient memory


The way you test for a failed allocation from a new expression depends on whether you
use the standard exception mechanism, or you use a nullptr return. Standard C++
expects an allocator to throw either std::bad_alloc or a class derived from
std::bad_alloc . You can handle such an exception as shown in this sample:
C++

#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
try {
int *pI = new int[BIG_NUMBER];
}
catch (bad_alloc& ex) {
cout << "Caught bad_alloc: " << ex.what() << endl;
return -1;
}
}

When you use the nothrow form of new , you can test for an allocation failure as shown
in this sample:

C++

#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new(nothrow) int[BIG_NUMBER];
if ( pI == nullptr ) {
cout << "Insufficient memory" << endl;
return -1;
}
}

You can test for a failed memory allocation when you've used nothrownew.obj file to
replace global operator new as shown here:

C++

#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new int[BIG_NUMBER];
if ( !pI ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
You can provide a handler for failed memory allocation requests. It's possible to write a
custom recovery routine to handle such a failure. It could, for example, release some
reserved memory, then allow the allocation to run again. For more information, see
_set_new_handler.

The delete operator


Memory that is dynamically allocated using the new operator can be freed using the
delete operator. The delete operator calls the operator delete function, which frees
memory back to the available pool. Using the delete operator also causes the class
destructor (if one exists) to be called.

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:

C++

void operator delete( void * );


void operator delete( void *, size_t );

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:
C++

#include <iostream>
using namespace std;

int fLogMemory = 0; // Perform logging (0=no; nonzero=yes)?


int cBlocksAllocated = 0; // Count of blocks allocated.

// User-defined operator new.


void *operator new( size_t stAllocateBlock ) {
static int fInOpNew = 0; // Guard flag.

if ( fLogMemory && !fInOpNew ) {


fInOpNew = 1;
clog << "Memory block " << ++cBlocksAllocated
<< " allocated for " << stAllocateBlock
<< " bytes\n";
fInOpNew = 0;
}
return malloc( stAllocateBlock );
}

// User-defined operator delete.


void operator delete( void *pvMem ) {
static int fInOpDelete = 0; // Guard flag.
if ( fLogMemory && !fInOpDelete ) {
fInOpDelete = 1;
clog << "Memory block " << cBlocksAllocated--
<< " deallocated\n";
fInOpDelete = 0;
}

free( pvMem );
}

int main( int argc, char *argv[] ) {


fLogMemory = 1; // Turn logging on
if( argc > 1 )
for( int i = 0; i < atoi( argv[1] ); ++i ) {
char *pMem = new char[10];
delete[] pMem;
}
fLogMemory = 0; // Turn logging off.
return cBlocksAllocated;
}

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:
C++

// 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++)
Article • 08/03/2021

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.

Uses for smart pointers


Smart pointers are defined in the std namespace in the <memory> header file. They
are crucial to the RAII or Resource Acquisition Is Initialization programming idiom. The
main goal of this idiom is to ensure that resource acquisition occurs at the same time
that the object is initialized, so that all resources for the object are created and made
ready in one line of code. In practical terms, the main principle of RAII is to give
ownership of any heap-allocated resource—for example, dynamically-allocated memory
or system object handles—to a stack-allocated object whose destructor contains the
code to delete or free the resource and also any associated cleanup code.

In most cases, when you initialize a raw pointer or resource handle to point to an actual
resource, pass the pointer to a smart pointer immediately. In modern C++, raw pointers
are only used in small code blocks of limited scope, loops, or helper functions where
performance is critical and there is no chance of confusion about ownership.

The following example compares a raw pointer declaration to a smart pointer


declaration.

C++

void UseRawPointer()
{
// Using a raw pointer -- not recommended.
Song* pSong = new Song(L"Nothing on You", L"Bruno Mars");

// Use pSong...

// Don't forget to delete!


delete 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_;
//...

} // song2 is deleted automatically here.

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.

C++

class LargeObject
{
public:
void DoSomething(){}
};

void ProcessLargeObject(const LargeObject& lo){}


void SmartPointerDemo()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());

//Call a method on the object


pLarge->DoSomething();

// Pass a reference to a method.


ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope.

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.

C++

void SmartPointerDemo2()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());

//Call a method on the object


pLarge->DoSomething();
// Free the memory before we exit function block.
pLarge.reset();

// Do some other work...

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.

C++

void SmartPointerDemo4()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());

//Call a method on the object


pLarge->DoSomething();

// Pass raw pointer to a legacy API


LegacyLargeObjectFunction(pLarge.get());
}

Kinds of smart pointers


The following section summarizes the different kinds of smart pointers that are available
in the Windows programming environment and describes when to use them.

C++ Standard Library smart pointers


Use these smart pointers as a first choice for encapsulating pointers to plain old C++
objects (POCO).

unique_ptr

Allows exactly one owner of the underlying pointer. Use as the default choice for
POCO unless you know for certain that you require a shared_ptr . Can be moved to
a new owner, but not copied or shared. Replaces auto_ptr , which is deprecated.
Compare to boost::scoped_ptr . unique_ptr is small and efficient; the size is one
pointer and it supports rvalue references for fast insertion and retrieval from C++
Standard Library collections. Header file: <memory> . For more information, see How
to: Create and Use unique_ptr Instances and unique_ptr Class.

shared_ptr

Reference-counted smart pointer. Use when you want to assign one raw pointer to
multiple owners, for example, when you return a copy of a pointer from a
container but want to keep the original. The raw pointer is not deleted until all
shared_ptr owners have gone out of scope or have otherwise given up ownership.
The size is two pointers; one for the object and one for the shared control block
that contains the reference count. Header file: <memory> . For more information, see
How to: Create and Use shared_ptr Instances and shared_ptr Class.

weak_ptr

Special-case smart pointer for use in conjunction with shared_ptr . A weak_ptr


provides access to an object that is owned by one or more shared_ptr instances,
but does not participate in reference counting. Use when you want to observe an
object, but do not require it to remain alive. Required in some cases to break
circular references between shared_ptr instances. Header file: <memory> . For more
information, see How to: Create and Use weak_ptr Instances and weak_ptr Class.

Smart pointers for COM objects (classic Windows


programming)
When you work with COM objects, wrap the interface pointers in an appropriate smart
pointer type. The Active Template Library (ATL) defines several smart pointers for various
purposes. You can also use the _com_ptr_t smart pointer type, which the compiler uses
when it creates wrapper classes from .tlb files. It's the best choice when you do not want
to include the ATL header files.

CComPtr Class
Use this unless you cannot use ATL. Performs reference counting by using the AddRef
and Release methods. For more information, see How to: Create and Use CComPtr and
CComQIPtr Instances.

CComQIPtr Class
Resembles CComPtr but also provides simplified syntax for calling QueryInterface on
COM objects. For more information, see How to: Create and Use CComPtr and
CComQIPtr Instances.

CComHeapPtr Class
Smart pointer to objects that use CoTaskMemFree to free memory.
CComGITPtr Class
Smart pointer for interfaces that are obtained from the global interface table (GIT).

_com_ptr_t Class
Resembles CComQIPtr in functionality but does not depend on ATL headers.

ATL smart pointers for POCO objects


In addition to smart pointers for COM objects, ATL also defines smart pointers, and
collections of smart pointers, for plain old C++ objects (POCO). In classic Windows
programming, these types are useful alternatives to the C++ Standard Library
collections, especially when code portability is not required or when you do not want to
mix the programming models of the C++ Standard Library and ATL.

CAutoPtr Class
Smart pointer that enforces unique ownership by transferring ownership on copy.
Comparable to the deprecated std::auto_ptr Class.

CHeapPtr Class
Smart pointer for objects that are allocated by using the C malloc function.

CAutoVectorPtr Class
Smart pointer for arrays that are allocated by using new[] .

CAutoPtrArray Class
Class that encapsulates an array of CAutoPtr elements.

CAutoPtrList Class
Class that encapsulates methods for manipulating a list of CAutoPtr nodes.

See also
Pointers
C++ Language Reference
C++ Standard Library
How to: Create and use unique_ptr
instances
Article • 11/12/2021

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.

C++

unique_ptr<Song> SongFactory(const std::wstring& artist, const std::wstring&


title)
{
// Implicit move operation into the variable that stores the result.
return make_unique<Song>(artist, title);
}

void MakeSongs()
{
// Create a new unique_ptr with a new object.
auto song = make_unique<Song>(L"Mr. Children", L"Namonaki Uta");

// Use the unique_ptr.


vector<wstring> titles = { song->title };

// Move raw pointer from one unique_ptr to another.


unique_ptr<Song> song2 = std::move(song);

// Obtain unique_ptr from function that returns by value.


auto song3 = SongFactory(L"Michael Jackson", L"Beat It");
}

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.

C++

void SongVector()
{
vector<unique_ptr<Song>> songs;

// Create a few new unique_ptr<Song> instances


// and add them to vector using implicit move semantics.
songs.push_back(make_unique<Song>(L"B'z", L"Juice"));
songs.push_back(make_unique<Song>(L"Namie Amuro", L"Funky Town"));
songs.push_back(make_unique<Song>(L"Kome Kome Club", L"Kimi ga Iru Dake
de"));
songs.push_back(make_unique<Song>(L"Ayumi Hamasaki", L"Poker Face"));

// Pass by const reference when possible to avoid copying.


for (const auto& song : songs)
{
wcout << L"Artist: " << song->artist << L" Title: " << song->title
<< endl;
}
}
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.

C++

class MyClass
{
private:
// MyClass owns the unique_ptr.
unique_ptr<ClassFactory> factory;
public:

// Initialize by using make_unique with ClassFactory default


constructor.
MyClass() : factory (make_unique<ClassFactory>())
{
}

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.

C++

// Create a unique_ptr to an array of 5 integers.


auto p = make_unique<int[]>(5);

// Initialize the array.


for (int i = 0; i < 5; ++i)
{
p[i] = i;
wcout << p[i] << endl;
}
For more examples, see make_unique.

See also
Smart Pointers (Modern C++)
make_unique
How to: Create and Use shared_ptr
instances
Article • 03/20/2024

The shared_ptr type is a smart pointer in the C++ standard library that is designed for
scenarios in which more than one owner needs to manage the lifetime of an object.
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:

C++

// 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
};

struct Song : public MediaAsset


{
std::wstring artist;
std::wstring title;
Song(const std::wstring& artist_, const std::wstring& title_) :
artist{ artist_ }, title{ title_ } {}
};

struct Photo : public MediaAsset


{
std::wstring date;
std::wstring location;
std::wstring subject;
Photo(
const std::wstring& date_,
const std::wstring& location_,
const std::wstring& subject_) :
date{ date_ }, location{ location_ }, subject{ subject_ } {}
};

using namespace std;

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.

C++

// Use make_shared function when possible.


auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With
You");

// Ok, but slightly less efficient.


// Note: Using new expression as constructor argument
// creates no named variable for other code to access.
shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));

// When initialization must be separate from declaration, e.g. class


members,
// initialize with nullptr to make your programming intent explicit.
shared_ptr<Song> sp5(nullptr);
//Equivalent to: shared_ptr<Song> sp5;
//...
sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");

Example 2
The following example shows how to declare and initialize shared_ptr instances that
take on shared ownership of an object that was allocated by another shared_ptr .
Assume that sp2 is an initialized shared_ptr .

C++

//Initialize with copy constructor. Increments ref count.


auto sp3(sp2);

//Initialize via assignment. Increments ref count.


auto sp4 = sp2;

//Initialize with nullptr. sp7 is empty.


shared_ptr<Song> sp7(nullptr);

// Initialize with another shared_ptr. sp1 and sp2


// swap pointers as well as ref counts.
sp1.swap(sp2);

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.

C++

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;
});

for (const auto& s : v2)


{
wcout << s->artist << L":" << s->title << endl;
}

Example 4
You can use dynamic_pointer_cast , static_pointer_cast , and const_pointer_cast to
cast a shared_ptr . These functions resemble the dynamic_cast , static_cast , and
const_cast operators. The following example shows how to test the derived type of

each element in a vector of shared_ptr of base classes, and then copies the elements
and display information about them.

C++

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;

copy_if(assets.begin(), assets.end(), back_inserter(photos), []


(shared_ptr<MediaAsset> p) -> bool
{
// Use dynamic_pointer_cast to test whether
// element is a shared_ptr<Photo>.
shared_ptr<Photo> temp = dynamic_pointer_cast<Photo>(p);
return temp.get() != nullptr;
});

for (const auto& p : photos)


{
// We know that the photos vector contains only
// shared_ptr<Photo> objects, so use static_cast.
wcout << "Photo location: " << (static_pointer_cast<Photo>(p))->location
<< endl;
}

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 uses 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.

C++

void use_shared_ptr_by_value(shared_ptr<int> sp);

void use_shared_ptr_by_reference(shared_ptr<int>& sp);


void use_shared_ptr_by_const_reference(const shared_ptr<int>& sp);

void use_raw_pointer(int* p);


void use_reference(int& r);

void test() {
auto sp = make_shared<int>(5);

// Pass the shared_ptr by value.


// This invokes the copy constructor, increments the reference count,
and makes the callee an owner.
use_shared_ptr_by_value(sp);

// Pass the shared_ptr by reference or const reference.


// In this case, the reference count isn't incremented.
use_shared_ptr_by_reference(sp);
use_shared_ptr_by_const_reference(sp);

// Pass the underlying pointer or a reference to the underlying object.


use_raw_pointer(sp.get());
use_reference(*sp);

// Pass the shared_ptr by value.


// This invokes the move constructor, which doesn't increment the
reference count
// but in fact transfers ownership to the callee.
use_shared_ptr_by_value(move(sp));
}

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.
C++

// Initialize two separate raw pointers.


// Note that they contain the same values.
auto song1 = new Song(L"Village People", L"YMCA");
auto song2 = new Song(L"Village People", L"YMCA");

// Create two unrelated shared_ptrs.


shared_ptr<Song> p1(song1);
shared_ptr<Song> p2(song2);

// Unrelated shared_ptrs are never equal.


wcout << "p1 < p2 = " << std::boolalpha << (p1 < p2) << endl;
wcout << "p1 == p2 = " << std::boolalpha <<(p1 == p2) << endl;

// Related shared_ptr instances are always equal.


shared_ptr<Song> p3(p2);
wcout << "p3 == p2 = " << std::boolalpha << (p3 == p2) << endl;

See also
Smart Pointers (Modern C++)

Feedback
Was this page helpful?  Yes  No

Provide product feedback | Get help at Microsoft Q&A


How to: Create and use weak_ptr
instances
Article • 08/03/2021

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 .

C++

#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

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;
}

// Demonstrates how to test whether the


// pointed-to memory still exists or not.
void CheckStatuses() const
{
for_each(others.begin(), others.end(), [](weak_ptr<Controller> wp) {
auto p = wp.lock();
if (p)
{
wcout << L"Status of " << p->Num << " = " << p->Status << endl;
}
else
{
wcout << L"Null object" << 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),
};

// Each controller depends on all others not being deleted.


// Give each controller a pointer to all the others.
for (int i = 0; i < v.size(); ++i)
{
for_each(v.begin(), v.end(), [&v, i](shared_ptr<Controller> p) {
if (p->Num != i)
{
v[i]->others.push_back(weak_ptr<Controller>(p));
wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
}
});
}

for_each(v.begin(), v.end(), [](shared_ptr<Controller> &p) {


wcout << L"use_count = " << p.use_count() << endl;
p->CheckStatuses();
});
}

int main()
{
RunTest();
wcout << L"Press any key" << endl;
char ch;
cin.getline(&ch, 1);
}

Output

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
Article • 08/03/2021

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.

C++

void CComPtrDemo()
{

HRESULT hr = CoInitialize(NULL);

// Declare the smart pointer.


CComPtr<IGraphBuilder> pGraph;

// Use its member function CoCreateInstance to


// create the COM object and obtain the IGraphBuilder pointer.
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if(FAILED(hr)){ /*... handle hr error*/ }

// Use the overloaded -> operator to call the interface methods.


hr = pGraph->RenderFile(L"C:\\Users\\Public\\Music\\Sample Music\\Sleep
Away.mp3", NULL);
if(FAILED(hr)){ /*... handle hr error*/ }

// Declare a second smart pointer and use it to


// obtain another interface from the object.
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }

// Obtain a third interface.


CComPtr<IMediaEvent> pEvent;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
if(FAILED(hr)){ /*... handle hr error*/ }

// Use the second interface.


hr = pControl->Run();
if(FAILED(hr)){ /*... handle hr error*/ }

// Use the third interface.


long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);

CoUninitialize();

// Let the smart pointers do all reference counting.


}

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.

C++

// CComPtr with error handling:


CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }
// CComQIPtr with error handling
CComQIPtr<IMediaEvent> pEvent = pControl;
if(!pEvent){ /*... handle NULL pointer error*/ }

// Use the second interface.


hr = pControl->Run();
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> .

C++

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*/ }

// Make Word visible.


hr = pWord.PutPropertyByName(_bstr_t("Visible"), &_variant_t(1));
if(FAILED(hr)){ /*... handle hr error*/ }

// Get the Documents collection and store it in new CComPtr


hr = pWord.GetPropertyByName(_bstr_t("Documents"), &pOutVal);
if(FAILED(hr)){ /*... handle hr error*/ }

CComPtr<IDispatch> pDocuments = pOutVal.pdispVal;

// Use Documents to open a document


hr = pDocuments.Invoke1 (_bstr_t("Open"),
&_variant_t("c:\\users\\public\\documents\\sometext.txt"),&pOutVal);
if(FAILED(hr)){ /*... handle hr error*/ }

CoUninitialize();
}

See also
Smart Pointers (Modern C++)

You might also like