An Overture to C Programmers
xlix
Listing 19 shows how to sort a container of values using a few lines of code.
#include
#include
#include
int main() {
std::vector x{ 0, 1, 8, 13, 5, 2, 3 };
u
x[0] = 21;
v
x.push_back(1);
w
std::sort(x.begin(), x.end());
x
std::cout << "Printing " << x.size() << " Fibonacci numbers.\n";
y
for (auto number : x) {
std::cout << number << std::endl;
z
}
}
Listing 19: Sorting a container of values using the stdlib
A good amount of computation is going on in the background, yet the
code is compact and expressive. First, you initialize a
std::vector
container
u
.
Vectors are the stdlib’s dynamically sized arrays. The initializer braces (the
{0, 1, ...}
) set the initial values contained in
x
. You can access the elements
of a
vector
just like the elements of an array using brackets (
[]
) and the index
number. You use this technique to set the first element equal to
21
v
. Because
vector
arrays are dynamically sized, you can append values to them using the
push_back
method
w
. The seemingly magical invocation of
std::sort
showcases
the power of the algorithms in stdlib
x
. The methods
x.begin()
and
x.end()
return iterators that
std::sort
uses to sort
x
in place. The
sort
algorithm is
decoupled from
vector
through the use of iterators.
Thanks to iterators, you can use other containers in stdlib similarly. For
example, you could use a
list
(the stdlib’s doubly linked list) rather than
using a
vector
. Because
list
also exposes iterators through
.begin()
and
.end()
methods, you could call
sort
on the list iterators in the same way.
Additionally, Listing 19 uses iostreams. Iostreams are the stdlib’s mecha-
nism for performing buffered input and output. You use the put-to operator
(
<<
) to stream the value of
x.size()
(the number of elements in
x
), some
string literals, and the Fibonacci element
number
to
std::cout
, which encapsu-
lates stdout
y
z
. The
std::endl
object is an I/O manipulator that writes
\n
and flushes the buffer, ensuring that the entire stream is written to stdout
before executing the next instruction.
Now, just imagine all the hoops you’d have to jump through to write an
equivalent program in C, and you’ll see why the stdlib is such a valuable tool.
Lambdas
Lambdas, also called unnamed or anonymous functions in some circles, are
another powerful language feature that improve the locality of code. In
some cases, you should pass pointers to functions to use a pointer as the tar-
get of a newly created thread or to perform some transformation on each
element of a sequence. It’s generally inconvenient to define a one-time-use
l
An Overture to C Programmers
free function. That’s where lambdas come in.
A lambda is a new, custom
function
defined inline with the other parameters of an invocation. Consider the
following one-liner, which computes the count of even numbers in
x
:
auto n_evens = std::count_if(x.begin(), x.end(),
[] (auto number) { return number % 2 == 0; });
This snippet uses the stdlib’s
count_if
algorithm to count the even num-
bers in
x
. The first two arguments to
std::count_if
match
std::sort
; they’re
the iterators that define the range over which the algorithm will operate.
The third argument is the lambda. The notation probably looks a bit for-
eign, but the basics are quite simple:
[
capture
] (
arguments
) {
body
}
Capture contains any objects you need from the scope where the lambda
is defined to perform computation in the body.
Arguments define
the names
and types of arguments the lambda expects to be invoked with. The
body
contains any computation that you want completed upon invocation. It
might or might not return a value. The compiler will deduce the function
prototype based on the types you’ve implied.
In the
std::count_if
invocation above, the lambda didn’t need to
capture any variables. All the information it needs is taken as a single
argument
number
. Because the compiler knows the type of the elements
contained in
x
, you declare the type of
number
with
auto
so the compiler
can deduce it for you. The lambda is invoked with each element of
x
passed in as the
number
parameter. In the body,
the lambda returns
true
only when
number
is divisible by
2
, so only the even numbers are included
in the count.
Lambdas don’t exist in C, and it’s not really possible to reconstruct
them. You’d need to declare a separate function each time you need a func-
tion object, and it’s not possible to capture objects into a function in the
same way.
Dostları ilə paylaş: