Cplusplus
Cplusplus
#c++
Table of Contents
About 1
Remarks 2
Versions 2
Examples 2
Hello World 2
Analysis 2
Comments 4
Single-Line Comments 4
C-Style/Block Comments 4
Importance of Comments 5
Function 6
Function Declaration 6
Function Call 7
Function Definition 7
Function Overloading 8
Default Parameters 8
Preprocessor 11
Chapter 2: Alignment 13
Introduction 13
Remarks 13
Examples 13
Controlling alignment 14
Introduction 17
Examples 17
Chapter 5: Arrays 19
Introduction 19
Examples 19
Array initialization 25
Syntax 27
Remarks 27
Examples 27
Multi-threaded Access 27
Chapter 7: Attributes 29
Syntax 29
Examples 29
[[noreturn]] 29
[[fallthrough]] 30
[[nodiscard]] 31
[[maybe_unused]] 32
Chapter 8: auto 34
Remarks 34
Examples 34
Remarks 38
Examples 38
Examples 40
int 40
bool 40
char 40
char16_t 40
char32_t 41
float 41
double 41
long 41
short 42
void 42
wchar_t 42
Introduction 44
Remarks 44
Examples 45
Remarks 46
Examples 46
Setting a bit 46
Clearing a bit 46
C-style bit-manipulation 46
Using std::bitset 47
Toggling a bit 47
C-style bit-manipulation 47
Using std::bitset 47
Checking a bit 47
C-style bit-manipulation 47
Using std::bitset 48
C-style bit-manipulation 48
Using std::bitset 48
C-style bit-manipulation 48
Using std::bitset 48
C-style bit-manipulation 48
Remarks 52
Examples 52
| - bitwise OR 53
Remarks 58
Examples 58
Introduction 59
Basic rules 59
Incremental builds 60
Documentation 61
Ninja 62
Introduction 62
Introduction 62
Autotools (GNU) 63
Introduction 63
Introduction 64
Examples 64
Reserved Keywords 64
goto or switch 64
Introduction 65
Examples 65
Introduction 68
Remarks 68
Examples 68
Clean code 71
Conclusion 73
Static analysis 73
Compiler warnings 74
External tools 74
Other tools 75
Conclusion 75
Conclusion 76
Introduction 77
Examples 77
Call by value 77
Remarks 79
Examples 79
String streams 79
Copying streams 81
Arrays 82
Printing collections with iostream 82
Basic printing 82
Arrays 83
Parsing files 83
Transformation 84
Remarks 86
Atomic Operations 86
Sequential Consistency 87
Relaxed Ordering 87
Release-Acquire Ordering 87
Release-Consume Ordering 88
Fences 88
Examples 88
Fence example 90
Introduction 92
Remarks 92
Examples 92
Function Pointers 92
Syntax 94
Remarks 94
Examples 94
Class basics 94
Access specifiers 95
Inheritance 96
Virtual Inheritance 98
Multiple Inheritance 99
Background 102
Friendship 104
Examples 122
Examples 127
Variables 127
Functions 127
Introduction 130
Remarks 130
Examples 130
Introduction 153
Remarks 153
Examples 153
Syntax 157
Remarks 157
Examples 157
Syntax 167
Remarks 167
Examples 167
Examples 171
Introduction 173
Remarks 173
Examples 173
Examples 179
Syntax 184
Parameters 184
Remarks 184
Examples 184
Introduction 188
Examples 188
Examples 195
Introduction 197
Examples 197
Introduction 199
Remarks 199
Examples 199
Examples 209
Examples 210
Examples 214
std::uncaught_exceptions 220
Introduction 224
Syntax 224
Remarks 224
Examples 225
void* to T* 230
Examples 232
File vec.hh : wrapper for std::vector, used to show log when a construction is called. 234
File expr.hh : implementation of expression templates for element-wise operations (vector 235
Introduction 246
Examples 246
Examples 258
Remarks 260
Examples 260
case 260
switch 260
catch 261
default 261
if 262
else 262
goto 262
return 263
throw 263
try 264
Conditional Structures: if, if..else 264
Remarks 270
Examples 270
Introduction 273
Examples 273
Introduction 276
Remarks 276
Examples 276
Remarks 281
Examples 281
Introduction 282
Examples 282
Remarks 287
Examples 287
Examples 290
Introduction 298
Syntax 298
Remarks 298
FAQs 298
See Also 299
Examples 299
Introduction 301
Examples 301
Remarks 302
Examples 302
Examples 304
break 304
continue 304
do 304
for 304
while 305
Examples 306
Overview 307
Introduction 315
Syntax 315
Remarks 315
Examples 317
asm 317
explicit 317
noexcept 318
typename 319
sizeof 320
Syntax 326
Parameters 326
Remarks 326
Examples 327
Remarks 343
Examples 343
Arrays 346
Introduction 348
Syntax 348
Remarks 348
Examples 348
Introduction 350
Examples 350
true 350
false 350
nullptr 350
this 351
Introduction 354
Syntax 354
Remarks 354
Examples 354
Syntax 365
Remarks 365
Examples 365
Stack 365
Introduction 370
Remarks 370
Examples 370
If-then-else 379
Introduction 380
Examples 380
Examples 381
Examples 389
Remarks 391
Examples 399
std::mutex 401
std::lock 402
Introduction 403
Syntax 403
Remarks 403
Examples 404
What are namespaces? 404
Syntax 413
Remarks 413
Examples 413
Encapsulation 414
Examples 421
Introduction 424
Remarks 424
Examples 424
Remarks 440
Examples 440
Introduction 444
Examples 444
Examples 446
Example 449
When to use? 450
Remarks 452
Examples 452
Examples 461
Remarks 462
Examples 462
Remarks 464
Examples 464
Introduction 466
Syntax 466
Remarks 466
Examples 466
Syntax 472
Examples 472
Examples 476
Introduction 480
Remarks 480
Examples 480
Macros 483
X-macros 489
Examples 493
Profiling CPU Usage with gcc and Google Perf Tools 495
Remarks 498
Examples 498
Locking 498
Finally/ScopeExit 499
Remarks 503
Examples 503
Examples 506
Using tail recursion and Fibonnaci-style recursion to solve the Fibonnaci sequence 506
Examples 508
std::recursive_mutex 508
Introduction 509
Examples 509
Examples 513
Defining a reference 513
Introduction 515
Syntax 515
Parameters 515
Examples 516
Quantifiers 518
Anchors 520
Introduction 521
Examples 521
Remarks 524
Examples 524
1. Base example without covariant returns, shows why they're desirable 524
2. Covariant result version of the base example, static type checking. 525
Introduction 528
Examples 528
Examples 536
dynamic_cast 536
Examples 538
Introduction 540
Examples 540
Examples 542
enable_if 542
void_t 544
is_detected 548
Chapter 100: Side by Side Comparisons of classic C++ examples solved via C++ vs C++11 vs C
552
Examples 552
Remarks 554
Examples 554
Subclasses 555
Syntax 558
Remarks 558
Examples 558
Remarks 572
Examples 572
Destructor 584
Examples 587
std::for_each 587
std::next_permutation 587
std::accumulate 588
std::find 590
std::count 591
std::count_if 592
std::find_if 593
std::min_element 595
Syntax 598
Parameters 598
Remarks 598
Examples 598
static_assert 598
Remarks 600
Examples 600
Parameters 601
Remarks 601
Examples 601
Examples 606
Introduction 609
Remarks 609
Examples 609
Example 609
Methods 610
Examples 612
Introduction 619
Examples 619
Examples 622
std::setw 622
std::setprecision 622
std::setfill 623
std::setiosflags 623
Remarks 625
Examples 625
Multi-Map 632
Examples 634
Introduction 634
value_or 637
Examples 638
Introduction 640
Remarks 640
Examples 640
Introduction 647
Syntax 647
Remarks 648
Examples 648
Splitting 648
Concatenation 650
operator[](n) 651
at(n) 651
front() 651
back() 652
Tokenize 652
Remarks 664
Examples 664
Introduction 667
Remarks 667
Examples 667
Iterators: 675
Find max and min Element and Respective Index in a Vector 688
Introduction 691
Remarks 691
Examples 691
mutable 691
register 692
static 692
auto 693
extern 693
Introduction 695
Remarks 695
Examples 696
Introduction 706
Syntax 706
Remarks 706
Examples 708
Introduction 721
Remarks 721
Examples 722
C++11 722
Classes 723
Other Types 723
Templates 723
Concurrency 723
General 724
Concurrency 724
C++14 724
C++17 725
C++03 726
C++98 726
C++20 727
Examples 728
Remarks 734
Examples 734
Using the this Pointer to Differentiate Between Member Data and Parameters 737
Introduction 743
Examples 743
std::shared_lock 743
Syntax 746
Parameters 746
Remarks 746
Examples 746
Remarks 758
Examples 758
Remarks 760
Examples 760
Introduction 764
Examples 764
Introduction 777
Remarks 777
Examples 777
Examples 779
class 779
struct 780
enum 780
union 781
Chapter 134: Type Traits 783
Remarks 783
Examples 783
Constants 783
Functions 783
Types 784
Introduction 788
Syntax 788
Examples 788
Introduction 791
Remarks 791
Examples 792
Deleting a derived object via a pointer to a base class that doesn't have a virtual destru 798
Remarks 806
Examples 806
Introduction 808
Examples 808
Catch 808
Examples 810
Remarks 812
Examples 812
Examples 818
Introduction 822
Syntax 822
Remarks 822
Examples 822
Introduction 824
Remarks 824
Examples 824
Declaration and Usage 824
Examples 826
Definitions 828
Examples 830
prvalue 830
xvalue 831
lvalue 831
glvalue 831
rvalue 832
Examples 834
const 834
decltype 834
signed 835
unsigned 835
volatile 836
Syntax 837
Remarks 837
Examples 837
Credits 844
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: cplusplus
It is an unofficial and free C++ ebook created for educational purposes. All the content is extracted
from Stack Overflow Documentation, which is written by many hardworking individuals at Stack
Overflow. It is neither affiliated with Stack Overflow nor official C++.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
Chapter 1: Getting started with C++
Remarks
The 'Hello World' program is a common example that can be simply used to check compiler and
library presence. It uses the C++ standard library, with std::cout from <iostream>, and has only one
file to compile, minimizing the chance of possible user error during compilation.
The process for compiling a C++ program inherently differs between compilers and operating
systems. The topic Compiling and Building contains the details about how to compile C++ code on
different platforms for a variety of compilers.
Versions
Examples
Hello World
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
}
https://riptutorial.com/ 2
Analysis
Let's examine each part of this code in detail:
• #include <iostream> is a preprocessor directive that includes the content of the standard
C++ header file iostream.
iostream is a standard library header file that contains definitions of the standard input and
output streams. These definitions are included in the std namespace, explained below.
The standard input/output (I/O) streams provide ways for programs to get input from and
output to an external system -- usually the terminal.
• int main() { ... }defines a new function named main. By convention, the main function is
called upon execution of the program. There must be only one main function in a C++
program, and it must always return a number of the int type.
Here, the int is what is called the function's return type. The value returned by the main
function is an exit code.
If no return statement is present, the main function (and thus, the program itself) returns 0 by
default. In this example, we don't need to explicitly write return 0;.
All other functions, except those that return the void type, must explicitly return a value
according to their return type, or else must not return at all.
• std::cout << "Hello World!" << std::endl; prints "Hello World!" to the standard output
stream:
○ std is a namespace, and :: is the scope resolution operator that allows look-ups for
objects by name within a namespace.
There are many namespaces. Here, we use :: to show we want to use cout from the
std namespace. For more information refer to Scope Resolution Operator - Microsoft
Documentation.
○ std::coutis the standard output stream object, defined in iostream, and it prints to the
standard output (stdout).
○ <<is, in this context, the stream insertion operator, so called because it inserts an
object into the stream object.
The standard library defines the << operator to perform data insertion for certain data
types into output streams. stream << content inserts content into the stream and returns
the same, but updated stream. This allows stream insertions to be chained: std::cout
<< "Foo" << " Bar"; prints "FooBar" to the console.
https://riptutorial.com/ 3
○ "Hello World!" is a character string literal, or a "text literal." The stream insertion
operator for character string literals is defined in file iostream.
○ std::endl is a special I/O stream manipulator object, also defined in file iostream.
Inserting a manipulator into a stream changes the state of the stream.
The stream manipulator std::endl does two things: first it inserts the end-of-line
character and then it flushes the stream buffer to force the text to show up on the
console. This ensures that the data inserted into the stream actually appear on your
console. (Stream data is usually stored in a buffer and then "flushed" in batches unless
you force a flush immediately.)
○ The semicolon (;) notifies the compiler that a statement has ended. All C++ statements
and class definitions require an ending/terminating semicolon.
Comments
A comment is a way to put arbitrary text inside source code without having the C++ compiler
interpret it with any functional meaning. Comments are used to give insight into the design or
method of a program.
Single-Line Comments
The double forward-slash sequence // will mark all text until a newline as a comment:
int main()
{
// This is a single-line comment.
int a; // this also is a single-line comment
int i; // this is another single-line comment
}
C-Style/Block Comments
The sequence /* is used to declare the start of the comment block and the sequence */ is used to
declare the end of comment. All text between the start and end sequences is interpreted as a
comment, even if the text is otherwise valid C++ syntax. These are sometimes called "C-style"
comments, as this comment syntax is inherited from C++'s predecessor language, C:
https://riptutorial.com/ 4
int main()
{
/*
* This is a block comment.
*/
int a;
}
In any block comment, you can write anything you want. When the compiler encounters the
symbol */, it terminates the block comment:
int main()
{
/* A block comment with the symbol /*
Note that the compiler is not affected by the second /*
however, once the end-block-comment symbol is reached,
the comment ends.
*/
int a;
}
The above example is valid C++ (and C) code. However, having additional /* inside a block
comment might result in a warning on some compilers.
Block comments can also start and end within a single line. For example:
Importance of Comments
As with all programming languages, comments provide several benefits:
The need for comments can be reduced by writing clear, self-documenting code. A simple
example is the use of explanatory names for variables, functions, and types. Factoring out logically
related tasks into discrete functions goes hand-in-hand with this.
https://riptutorial.com/ 5
During development, comments can also be used to quickly disable portions of code without
deleting it. This is often useful for testing or debugging purposes, but is not good style for anything
other than temporary edits. This is often referred to as “commenting out”.
Similarly, keeping old versions of a piece of code in a comment for reference purposes is frowned
upon, as it clutters files while offering little value compared to exploring the code's history via a
versioning system.
Function
Functions can accept arguments or values and return a single value (or not). To use a function, a
function call is used on argument values and the use of the function call itself is replaced with its
return value.
Every function has a type signature -- the types of its arguments and the type of its return type.
Functions are inspired by the concepts of the procedure and the mathematical function.
• Note: C++ functions are essentially procedures and do not follow the exact definition or rules
of mathematical functions.
Functions are often meant to perform a specific task. and can be called from other parts of a
program. A function must be declared and defined before it is called elsewhere in a program.
• Note: popular function definitions may be hidden in other included files (often for
convenience and reuse across many files). This is a common use of header files.
Function Declaration
A function declaration is declares the existence of a function with its name and type signature to
the compiler. The syntax is as the following:
int add2(int i); // The function is of the type (int) -> (int)
In the example above, the int add2(int i) function declares the following to the compiler:
The first argument will be referred to in the function's contents by the name i.
○
The argument name is optional; the declaration for the function could also be the following:
https://riptutorial.com/ 6
Per the one-definition rule, a function with a certain type signature can only be declared or
defined once in an entire C++ code base visible to the C++ compiler. In other words, functions with
a specific type signature cannot be re-defined -- they must only be defined once. Thus, the
following is not valid C++:
int add2(int i); // The compiler will note that add2 is a function (int) -> int
int add2(int j); // As add2 already has a definition of (int) -> int, the compiler
// will regard this as an error.
If a function returns nothing, its return type is written as void. If it takes no parameters, the
parameter list should be empty.
void do_something(); // The function takes no parameters, and does not return anything.
// Note that it can still affect variables it has access to.
Function Call
A function can be called after it has been declared. For example, the following program calls add2
with the value of 2 within the function of main:
#include <iostream>
int main()
{
std::cout << add2(2) << "\n"; // add2(2) will be evaluated at this point,
// and the result is printed.
return 0;
}
Function Definition
A function definition* is similar to a declaration, except it also contains the code that is executed
when the function is called within its body.
int add2(int i) // Data that is passed into (int i) will be referred to by the name i
{ // while in the function's curly brackets or "scope."
https://riptutorial.com/ 7
// add2.
}
Function Overloading
You can create multiple functions with the same name but different parameters.
int add2(int i, int j) // However, when add2() is called with two parameters, the
{ // code from the initial declaration will be overloaded,
int k = i + j + 2 ; // and the code in this declaration will be evaluated
return k; // instead.
}
Both functions are called by the same name add2, but the actual function that is called depends
directly on the amount and type of the parameters in the call. In most cases, the C++ compiler can
compute which function to call. In some cases, the type must be explicitly stated.
Default Parameters
Default values for function parameters can only be specified in function declarations.
In this example, multiply() can be called with one or two parameters. If only one parameter is
given, b will have default value of 7. Default arguments must be placed in the latter arguments of
the function. For example:
Certain special character sequences that will be reduced to function calls by the compiler, such as
!, +, -, *, %, and << and many more. These special characters are normally associated with non-
https://riptutorial.com/ 8
programming usage or are used for aesthetics (e.g. the + character is commonly recognized as the
addition symbol both within C++ programming as well as in elementary math).
C++ handles these character sequences with a special syntax; but, in essence, each occurrence
of an operator is reduced to a function call. For example, the following C++ expression:
3+3
operator+(3, 3)
While in C++'s immediate predecessor, C, operator function names cannot be assigned different
meanings by providing additional definitions with different type signatures, in C++, this is valid.
"Hiding" additional function definitions under one unique function name is referred to as operator
overloading in C++, and is a relatively common, but not universal, convention in C++.
In C++, code must be declared or defined before usage. For example, the following produces a
compile time error:
int main()
{
foo(2); // error: foo is called, but has not yet been declared
}
There are two ways to resolve this: putting either the definition or declaration of foo() before its
usage in main(). Here is one example:
int main()
{
foo(2); // OK: foo is completely defined beforehand, so it can be called here.
}
https://riptutorial.com/ 9
}
The prototype must specify the return type (void), the name of the function (foo), and the argument
list variable types (int), but the names of the arguments are NOT required.
One common way to integrate this into the organization of source files is to make a header file
containing all of the prototype declarations:
// foo.h
void foo(int); // prototype declaration
and then, once compiled, link the corresponding object file foo.o into the compiled object file
where it is used in the linking phase, main.o:
An “unresolved external symbol” error occurs when the function prototype and call exist, but the
function body is not defined. These can be trickier to resolve as the compiler won't report the error
until the final linking stage, and it doesn't know which line to jump to in the code to show the error.
A compiler is a program that translates code from a programming language into another form
which is (more) directly executable for a computer. Using a compiler to translate code is called
compilation.
C++ inherits the form of its compilation process from its "parent" language, C. Below is a list
showing the four major steps of compilation in C++:
1. The C++ preprocessor copies the contents of any included header files into the source code
file, generates macro code, and replaces symbolic constants defined using #define with their
values.
2. The expanded source code file produced by the C++ preprocessor is compiled into assembly
https://riptutorial.com/ 10
language appropriate for the platform.
3. The assembler code generated by the compiler is assembled into appropriate object code for
the platform.
4. The object code file generated by the assembler is linked together with the object code files
for any library functions used to produce an executable file.
• Note: some compiled code is linked together, but not to create a final program. Usually, this
"linked" code can also be packaged into a format that can be used by other programs. This
"bundle of packaged, usable code" is what C++ programmers refer to as a library.
Many C++ compilers may also merge or un-merge certain parts of the compilation process for
ease or for additional analysis. Many C++ programmers will use different tools, but all of the tools
will generally follow this generalized process when they are involved in the production of a
program.
The link below extends this discussion and provides a nice graphic to help. [1]:
http://faculty.cs.niu.edu/~mcmahon/CS241/Notes/compile.html
Preprocessor
It edits the source code, cutting some bits out, changing others, and adding other things.
In source files, we can include preprocessor directives. These directives tells the preprocessor to
perform specific actions. A directive starts with a # on a new line. Example:
#define ZERO 0
#include <something>
directive. What it does is takes all of something and inserts it in your file where the directive was.
The hello world program starts with the line
#include <iostream>
This line adds the functions and objects that let you use the standard input and output.
The C language, which also uses the preprocessor, does not have as many header files as the
C++ language, but in C++ you can use all the C header files.
https://riptutorial.com/ 11
directive. This tells the preprocessor that as it goes along the file, it should replace every
occurrence of something with something_else. It can also make things similar to functions, but that
probably counts as advanced C++.
The something_else is not needed, but if you define something as nothing, then outside preprocessor
directives, all occurrences of something will vanish.
This actually is useful, because of the #if,#else and #ifdef directives. The format for these would
be the following:
#if something==true
//code
#else
//more code
#endif
#ifdef thing_that_you_want_to_know_if_is_defined
//code
#endif
These directives insert the code that is in the true bit, and deletes the false bits. this can be used
to have bits of code that are only included on certain operating systems, without having to rewrite
the whole code.
https://riptutorial.com/ 12
Chapter 2: Alignment
Introduction
All types in C++ have an alignment. This is a restriction on the memory address that objects of that
type can be created within. A memory address is valid for an object's creation if dividing that
address by the object's alignment is a whole number.
Remarks
The standard guarantees the following:
• The alignment requirement of a type is a divisor of its size. For example, a class with size 16
bytes could have an alignment of 1, 2, 4, 8, or 16, but not 32. (If a class's members only total
14 bytes in size, but the class needs to have an alignment requirement of 8, the compiler will
insert 2 padding bytes to make the class's size equal to 16.)
• The signed and unsigned versions of an integer type have the same alignment requirement.
• A pointer to void has the same alignment requirement as a pointer to char.
• The cv-qualified and cv-unqualified versions of a type have the same alignment requirement.
Note that while alignment exists in C++03, it was not until C++11 that it became possible to query
alignment (using alignof) and control alignment (using alignas).
Examples
Querying the alignment of a type
c++11
The alignment requirement of a type can be queried using the alignof keyword as a unary
operator. The result is a constant expression of type std::size_t, i.e., it can be evaluated at
compile time.
#include <iostream>
int main() {
std::cout << "The alignment requirement of int is: " << alignof(int) << '\n';
}
Possible output
If applied to an array, it yields the alignment requirement of the element type. If applied to a
https://riptutorial.com/ 13
reference type, it yields the alignment requirement of the referenced type. (References themselves
have no alignment, since they are not objects.)
Controlling alignment
C++11
The alignas keyword can be used to force a variable, class data member, declaration or definition
of a class, or declaration or definition of an enum, to have a particular alignment, if supported. It
comes in two forms:
• alignas(x), where x is a constant expression, gives the entity the alignment x, if supported.
• alignas(T), where T is a type, gives the entity an alignment equal to the alignment
requirement of T, that is, alignof(T), if supported.
If multiple alignas specifiers are applied to the same entity, the strictest one applies.
In this example, the buffer buf is guaranteed to be appropriately aligned to hold an int object, even
though its element type is unsigned char, which may have a weaker alignment requirement.
alignas cannot be used to give a type a smaller alignment than the type would have without this
declaration:
alignas, when given an integer constant expression, must be given a valid alignment. Valid
alignments are always powers of two, and must be greater than zero. Compilers are required to
support all valid alignments up to the alignment of the type std::max_align_t. They may support
larger alignments than this, but support for allocating memory for such objects is limited. The
upper limit on alignments is implementation dependent.
C++17 features direct support in operator new for allocating memory for over-aligned types.
https://riptutorial.com/ 14
Chapter 3: Argument Dependent Name
Lookup
Examples
What functions are found
Functions are found by first collecting a set of "associated classes" and "associated namespaces"
that include one ore more of the following, depending on the argument type T. First, let us show
the rules for classes, enumeration and class template specialization names.
All functions and templates within all associated namespaces are found by argument dependent
lookup. In addition, namespace-scope friend functions declared in associated classes are found,
which are normally not visible. Using directives are ignored, however.
All of the following example calls are valid, without qualifying f by the namespace name in the call.
namespace A {
struct Z { };
namespace I { void g(Z); }
using namespace I;
https://riptutorial.com/ 15
// example calls
f(A::X());
f(A::X::Y());
f(std::make_shared<A::X>());
https://riptutorial.com/ 16
Chapter 4: Arithmitic Metaprogramming
Introduction
These are example of using C++ template metaprogramming in processing arithmitic operations in
compile time.
Examples
Calculating power in O(log n)
This example shows an efficient way of calculating power using template metaprogramming.
Example Usage:
C++14
https://riptutorial.com/ 17
intermediateValue;
};
int main()
{
std::cout << powerDouble<2,-3>::value;
}
https://riptutorial.com/ 18
Chapter 5: Arrays
Introduction
Arrays are elements of the same type placed in adjoining memory locations. The elements can be
individually referenced by a unique identifier with an added index.
This allows you to declare multiple variable values of a specific type and access them individually
without needing to declare a variable for each value.
Examples
Array size: type safe at compile time.
//----------------------------------- Machinery:
//----------------------------------- Usage:
#include <iostream>
using namespace std;
auto main()
-> int
{
int const a[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 4};
Size const n = n_items( a );
int b[n] = {}; // An array of the same size as a.
(void) b;
cout << "Size = " << n << "\n";
}
The C idiom for array size, sizeof(a)/sizeof(a[0]), will accept a pointer as argument and will then
generally yield an incorrect result.
For C++11
std::extent<decltype(MyArray)>::value;
Example:
https://riptutorial.com/ 19
char MyArray[] = { 'X','o','c','e' };
const auto n = std::extent<decltype(MyArray)>::value;
std::cout << n << "\n"; // Prints 4
Up till C++17 (forthcoming as of this writing) C++ had no built-in core language or standard library
utility to obtain the size of an array, but this can be implemented by passing the array by reference
to a function template, as shown above. Fine but important point: the template size parameter is a
size_t, somewhat inconsistent with the signed Size function result type, in order to accommodate
the g++ compiler which sometimes insists on size_t for template matching.
With C++17 and later one may instead use std::size, which is specialized for arrays.
// Example of raw dynamic size array. It's generally better to use std::vector.
#include <algorithm> // std::sort
#include <iostream>
using namespace std;
auto main()
-> int
{
cout << "Sorting n integers provided by you.\n";
cout << "n? ";
int const n = int_from( cin );
int* a = new int[n]; // ← Allocation of array of n items.
sort( a, a + n );
for( int i = 0; i < n; ++i ) { cout << a[i] << ' '; }
cout << '\n';
delete[] a;
}
A program that declares an array T a[n]; where n is determined a run-time, can compile with
certain compilers that support C99 variadic length arrays (VLAs) as a language extension. But
VLAs are not supported by standard C++. This example shows how to manually allocate a
dynamic size array via a new[]-expression,
delete[] a;
https://riptutorial.com/ 20
The array allocated here has indeterminate values, but it can be zero-initialized by just adding an
empty parenthesis (), like this: new int[n](). More generally, for arbitrary item type, this performs a
value-initialization.
As part of a function down in a call hierarchy this code would not be exception safe, since an
exception before the delete[] expression (and after the new[]) would cause a memory leak. One
way to address that issue is to automate the cleanup via e.g. a std::unique_ptr smart pointer. But
a generally better way to address it is to just use a std::vector: that's what std::vector is there for.
int main()
{
cout << "Sorting integers provided by you.\n";
cout << "You can indicate EOF via F6 in Windows or Ctrl+D in Unix-land.\n";
vector<int> a; // ← Zero size by default.
while( cin )
{
cout << "One number, please, or indicate EOF: ";
int const x = int_from( cin );
if( !cin.fail() ) { a.push_back( x ); } // Expands as necessary.
}
std::vector is a standard library class template that provides the notion of a variable size array. It
takes care of all the memory management, and the buffer is contiguous so a pointer to the buffer
(e.g. &v[0] or v.data()) can be passed to API functions requiring a raw array. A vector can even be
expanded at run time, via e.g. the push_back member function that appends an item.
The complexity of the sequence of n push_back operations, including the copying or moving
involved in the vector expansions, is amortized O(n). “Amortized”: on average.
Internally this is usually achieved by the vector doubling its buffer size, its capacity, when a larger
buffer is needed. E.g. for a buffer starting out as size 1, and being repeatedly doubled as needed
for n=17 push_back calls, this involves 1 + 2 + 4 + 8 + 16 = 31 copy operations, which is less than
2×n = 34. And more generally the sum of this sequence can't exceed 2×n.
Compared to the dynamic size raw array example, this vector-based code does not require the
user to supply (and know) the number of items up front. Instead the vector is just expanded as
https://riptutorial.com/ 21
necessary, for each new item value specified by the user.
Output:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
C++ doesn't support special syntax for indexing a multi-dimensional array. Instead such an array
is viewed as an array of arrays (possibly of arrays, and so on), and the ordinary single index
notation [i] is used for each level. In the example above m[y] refers to row y of m, where y is a
zero-based index. Then this row can be indexed in turn, e.g. m[y][x], which refers to the xth item –
or column – of row y.
I.e. the last index varies fastest, and in the declaration the range of this index, which here is the
number of columns per row, is the last and “innermost” size specified.
Since C++ doesn't provide built-in support for dynamic size arrays, other than dynamic allocation,
a dynamic size matrix is often implemented as a class. Then the raw array matrix indexing
notation m[y][x] has some cost, either by exposing the implementation (so that e.g. a view of a
transposed matrix becomes practically impossible) or by adding some overhead and slight
inconvenience when it's done by returning a proxy object from operator[]. And so the indexing
notation for such an abstraction can and will usually be different, both in look-and-feel and in the
order of indices, e.g. m(x,y) or m.at(x,y) or m.item(x,y).
https://riptutorial.com/ 22
A dynamic size matrix using std::vector for storage.
Unfortunately as of C++14 there's no dynamic size matrix class in the C++ standard library. Matrix
classes that support dynamic size are however available from a number of 3rd party libraries,
including the Boost Matrix library (a sub-library within the Boost library).
If you don't want a dependency on Boost or some other library, then one poor man's dynamic size
matrix in C++ is just like
vector<vector<int>> m( 3, vector<int>( 7 ) );
… where vector is std::vector. The matrix is here created by copying a row vector n times where n
is the number of rows, here 3. It has the advantage of providing the same m[y][x] indexing
notation as for a fixed size raw array matrix, but it's a bit inefficient because it involves a dynamic
allocation for each row, and it's a bit unsafe because it's possible to inadvertently resize a row.
A more safe and efficient approach is to use a single vector as storage for the matrix, and map the
client code's (x, y) to a corresponding index in that vector:
//--------------------------------------------- Machinery:
#include <algorithm> // std::copy
#include <assert.h> // assert
#include <initializer_list> // std::initializer_list
#include <vector> // std::vector
#include <stddef.h> // ptrdiff_t
namespace my {
using Size = ptrdiff_t;
using std::initializer_list;
using std::vector;
public:
auto n_rows() const -> Size { return items_.size()/n_cols_; }
auto n_cols() const -> Size { return n_cols_; }
https://riptutorial.com/ 23
Matrix(): n_cols_( 0 ) {}
//--------------------------------------------- Usage:
using my::Matrix;
auto some_matrix()
-> Matrix<int>
{
return
{
{ 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19, 20, 21 }
};
}
#include <iostream>
#include <iomanip>
using namespace std;
auto main() -> int
{
Matrix<int> const m = some_matrix();
assert( m.n_cols() == 7 );
assert( m.n_rows() == 3 );
for( int y = 0, y_end = m.n_rows(); y < y_end; ++y )
{
for( int x = 0, x_end = m.n_cols(); x < x_end; ++x )
{
cout << setw( 4 ) << m.item( x, y ); // ← Note: not `m[y][x]`!
}
cout << '\n';
}
}
Output:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
https://riptutorial.com/ 24
The above code is not industrial grade: it's designed to show the basic principles, and serve the
needs of students learning C++.
For example, one may define operator() overloads to simplify the indexing notation.
Array initialization
An array is just a block of sequential memory locations for a specific type of variable. Arrays are
allocated the same way as normal variables, but with square brackets appended to its name []
that contain the number of elements that fit into the array memory.
The following example of an array uses the typ int, the variable name arrayOfInts, and the
number of elements [5] that the array has space for:
int arrayOfInts[5];
An array can be declared and initialized at the same time like this
When initializing an array by listing all of its members, it is not necessary to include the number of
elements inside the square brackets. It will be automatically calculated by the compiler. In the
following example, it's 5:
It is also possible to initialize only the first elements while allocating more space. In this case,
defining the length in brackets is mandatory. The following will allocate an array of length 5 with
partial initialization, the compiler initializes all remaining elements with the standard value of the
element type, in this case zero.
Arrays of other basic data types may be initialized in the same way.
char arrayOfChars[5]; // declare the array and allocate the memory, don't initialize
char arrayOfChars[5] = { 'a', 'b', 'c', 'd', 'e' } ; //declare and initialize
It is also important to take note that when accessing array elements, the array's element index(or
position) starts from 0.
int array[5] = { 10/*Element no.0*/, 20/*Element no.1*/, 30, 40, 50/*Element no.4*/};
std::cout << array[4]; //outputs 50
std::cout << array[0]; //outputs 10
https://riptutorial.com/ 25
Read Arrays online: https://riptutorial.com/cplusplus/topic/3017/arrays
https://riptutorial.com/ 26
Chapter 6: Atomic Types
Syntax
• std::atomic<T>
• std::atomic_flag
Remarks
std::atomic allows atomic access to a TriviallyCopyable type, it is implementation-dependent if this
is done via atomic operations or by using locks. The only guaranteed lock-free atomic type is
std::atomic_flag.
Examples
Multi-threaded Access
An atomic type can be used to safely read and write to a memory location shared between two
threads.
#include <thread>
#include <iostream>
//function will add all values including and between 'a' and 'b' to 'result'
void add(int a, int b, int * result) {
for (int i = a; i <= b; i++) {
*result += i;
}
}
int main() {
//a primitive data type has no thread safety
int shared = 0;
https://riptutorial.com/ 27
//rejoin the thread at the end of execution for cleaning purposes
addingThread.join();
return 0;
}
The above example may cause a corrupted read and can lead to undefined behavior.
#include <atomic>
#include <thread>
#include <iostream>
//function will add all values including and between 'a' and 'b' to 'result'
void add(int a, int b, std::atomic<int> * result) {
for (int i = a; i <= b; i++) {
//atomically add 'i' to result
result->fetch_add(i);
}
}
int main() {
//atomic template used to store non-atomic objects
std::atomic<int> shared = 0;
return 0;
}
The above example is safe because all store() and load() operations of the atomic data type
protect the encapsulated int from simultaneous access.
https://riptutorial.com/ 28
Chapter 7: Attributes
Syntax
• [[details]]: Simple no-argument attribute
Examples
[[noreturn]]
C++11
C++11 introduced the [[noreturn]] attribute. It can be used for a function to indicate that the
function does not return to the caller by either executing a return statement, or by reaching the end
if it's body (it is important to note that this does not apply to void functions, since they do return to
the caller, they just do not return any value). Such a function may end by calling std::terminate or
std::exit, or by throwing an exception. It is also worth noting that such a function can return by
executing longjmp.
For instance, the function below will always either throw an exception or call std::terminate, so it is
a good candidate for [[noreturn]]:
This kind of functionality allows the compiler to end a function without a return statement if it
knows the code will never be executed. Here, because the call to ownAssertFailureHandler (defined
above) in the code below will never return, the compiler does not need to add code below that call:
https://riptutorial.com/ 29
}
It is undefined behavior if the function will actually return, so the following is not allowed:
Note that the [[noreturn]] is mostly used in void functions. However, this is not a requirement,
allowing the functions to be used in generic programming:
template<class InconsistencyHandler>
double fortyTwoDivideBy(int i) {
if (i == 0)
i = InconsistencyHandler::correct(i);
return 42. / i;
}
struct InconsistencyThrower {
static [[noreturn]] int correct(int i) { ownAssertFailureHandler("Unknown
inconsistency"s); }
}
struct InconsistencyChangeToOne {
static int correct(int i) { return 1; }
}
• std::abort
• std::exit
• std::quick_exit
• std::unexpected
• std::terminate
• std::rethrow_exception
• std::throw_with_nested
• std::nested_exception::rethrow_nested
[[fallthrough]]
C++17
Whenever a case is ended in a switch, the code of the next case will get executed. This last one
can be prevented by using the ´break` statement. As this so-called fallthrough behavior can
introduce bugs when not intended, several compilers and static analyzers give a warning on this.
https://riptutorial.com/ 30
From C++17 on, a standard attribute was introduced to indicate that the warning is not needed
when the code is meant to fall through. Compilers can safely give warnings when a case is ended
without break or [[fallthrough]] and has at least one statement.
switch(input) {
case 2011:
case 2014:
case 2017:
std::cout << "Using modern C++" << std::endl;
[[fallthrough]]; // > No warning
case 1998:
case 2003:
standard = input;
}
See the proposal for more detailed examples on how [[fallthrough]] can be used.
C++14
C++14 introduced a standard way of deprecating functions via attributes. [[deprecated]] can be
used to indicate that a function is deprecated. [[deprecated("reason")]] allows adding a specific
reason which can be shown by the compiler.
// Provides specific message which helps other programmers fixing there code
[[deprecated("Use the variant with unique_ptr instead, this function will be removed in the
next release")]]
void function(std::auto_ptr<A> a);
[[nodiscard]]
C++17
https://riptutorial.com/ 31
The [[nodiscard]] attribute can be used to indicate that the return value of a function shouldn't be
ignored when you do a function call. If the return value is ignored, the compiler should give a
warning on this. The attribute can be added to:
• A function definition
• A type
Adding the attribute to a type has the same behaviour as adding the attribute to every single
function which returns this type.
template<typename Function>
[[nodiscard]] Finally<std::decay_t<Function>> onExit(Function &&f);
See the proposal for more detailed examples on how [[nodiscard]] can be used.
Note: The implementation details of Finally/onExit are omitted in the example, see
Finally/ScopeExit.
[[maybe_unused]]
The [[maybe_unused]] attribute is created for indicating in code that certain logic might not be used.
This if often linked to preprocessor conditions where this might be used or might not be used. As
compilers can give warnings on unused variables, this is a way of suppressing them by indicating
intent.
A typical example of variables which are needed in debug builds while unneeded in production are
return values indicating success. In the debug builds, the condition should be asserted, though in
production these asserts have been removed.
A more complex example are different kind of helper functions which are in an unnamed
namespace. If these functions aren't used during compilation, a compiler might give a warning on
them. Ideally you would like to guard them with the same preprocessor tags as the caller, though
as this might become complex the [[maybe_unused]] attribute is a more maintainable alternative.
namespace {
[[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath);
https://riptutorial.com/ 32
// TODO: Reuse this on BSD, MAC ...
[[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath);
}
See the proposal for more detailed examples on how [[maybe_unused]] can be used.
https://riptutorial.com/ 33
Chapter 8: auto
Remarks
The keyword auto is a typename that represents an automatically-deduced type.
It was already a reserved keyword in C++98, inherited from C. In old versions of C++, it could be
used to explicitly state that a variable has automatic storage duration:
int main()
{
auto int i = 5; // removing auto has no effect
}
Examples
Basic auto sample
with lambdas:
https://riptutorial.com/ 34
auto myMap = std::map<int,float>();
myMap.emplace(1,3.14);
The reason for the copy is that the returned type is actually std::pair<const int,float>!
auto can also cause problems where expression templates come into play:
auto mult(int c) {
return c * std::valarray<int>{1};
}
auto v = mult(3);
std::cout << v[0]; // some value that could be, but almost certainly is not, 3.
The reason is that operator* on valarray gives you a proxy object that refers to the valarray as a
means of lazy evaluation. By using auto, you're creating a dangling reference. Instead of mult had
returned a std::valarray<int>, then the code would definitely print 3.
The auto keyword by itself represents a value type, similar to int or char. It can be modified with
the const keyword and the & symbol to represent a const type or a reference type, respectively.
These modifiers can be combined.
In this example, s is a value type (its type will be inferred as std::string), so each iteration of the
for loop copies a string from the vector into s.
If the body of the loop modifies s (such as by calling s.append(" and stuff")), only this copy will be
modified, not the original member of strings.
On the other hand, if s is declared with auto& it will be a reference type (inferred to be std::string&
), so on each iteration of the loop it will be assigned a reference to a string in the vector:
for(auto& s : strings) {
std::cout << s << std::endl;
}
In the body of this loop, modifications to s will directly affect the element of strings that it
references.
Finally, if s is declared const auto&, it will be a const reference type, meaning that on each iteration
https://riptutorial.com/ 35
of the loop it will be assigned a const reference to a string in the vector:
Within the body of this loop, s cannot be modified (i.e. no non-const methods can be called on it).
When using auto with range-based for loops, it is generally good practice to use const auto& if the
loop body will not modify the structure being looped over, since this avoids unnecessary copies.
which is equivalent to
int main() {}
C++14
auto print = [](const auto& arg) { std::cout << arg << std::endl; };
print(42);
print("hello world");
struct lambda {
template <typename T>
auto operator ()(const T& arg) const {
std::cout << arg << std::endl;
}
};
and then
lambda print;
https://riptutorial.com/ 36
print(42);
print("hello world");
Sometimes auto may behave not quite as was expected by a programmer. It type deduces the
expression, even when type deduction is not the right thing to do.
Here flag would be not bool, but std::vector<bool>::reference, since for bool specialization of
template vector the operator [] returns a proxy object with conversion operator operator bool
defined.
When flags.push_back(true) modifies the container, this pseudo-reference could end up dangling,
referring to an element that no longer exists.
std::vector<bool> getFlags();
The vector is discarded immediately, so flag is a pseudo-reference to an element that has been
discarded. The call to foo invokes undefined behavior.
In cases like this you can declare a variable with auto and initialize it by casting to the type you
want to be deduced:
but at that point, simply replacing auto with bool makes more sense.
Another case where proxy objects can cause problems is expression templates. In that case, the
templates are sometimes not designed to last beyond the current full-expression for efficiency
sake, and using the proxy object on the next causes undefined behavior.
https://riptutorial.com/ 37
Chapter 9: Basic input/output in c++
Remarks
The standard library <iostream> defines few streams for input and output:
|stream | description |
|-------|----------------------------------|
|cin | standard input stream |
|cout | standard output stream |
|cerr | standard error (output) stream |
|clog | standard logging (output) stream |
Out of four streams mentioned above cin is basically used for user input and other three are used
for outputting the data. In general or in most coding environments cin (console input or standard
input) is keyboard and cout (console output or standard output) is monitor.
cin here extracts the input entered by the user and feeds in variable value. The value is extracted
only after user presses ENTER key.
cout here takes the string to be displayed and inserts it to standard output or monitor
All four streams are located in standard namespace std so we need to print std::stream for stream
stream to use it.
There is also a manipulator std::endl in code. It can be used only with output streams. It inserts
end of line '\n' character in the stream and flushes it. It causes immediately producing output.
Examples
user input and standard output
#include <iostream>
int main()
{
https://riptutorial.com/ 38
int value;
std::cout << "Enter a value: " << std::endl;
std::cin >> value;
std::cout << "The square of entered value is: " << value * value << std::endl;
return 0;
}
https://riptutorial.com/ 39
Chapter 10: Basic Type Keywords
Examples
int
Denotes a signed integer type with "the natural size suggested by the architecture of the execution
environment", whose range includes at least -32767 to +32767, inclusive.
int x = 2;
int y = 3;
int z = x + y;
Can be combined with unsigned, short, long, and long long (q.v.) in order to yield other integer
types.
bool
bool is_even(int x) {
return x%2 == 0;
}
const bool b = is_even(47); // false
char
An integer type which is "large enough to store any member of the implementation’s basic
character set". It is implementation-defined whether char is signed (and has a range of at least -
127 to +127, inclusive) or unsigned (and has a range of at least 0 to 255, inclusive).
char16_t
C++11
An unsigned integer type with the same size and alignment as uint_least16_t, which is therefore
large enough to hold a UTF-16 code unit.
https://riptutorial.com/ 40
char32_t
C++11
An unsigned integer type with the same size and alignment as uint_least32_t, which is therefore
large enough to hold a UTF-32 code unit.
float
A floating point type. Has the narrowest range out of the three floating point types in C++.
double
A floating point type. Its range includes that of float. When combined with long, denotes the long
double floating point type, whose range includes that of double.
long
Denotes a signed integer type that is at least as long as int, and whose range includes at least -
2147483647 to +2147483647, inclusive (that is, -(2^31 - 1) to +(2^31 - 1)). This type can also be
written as long int.
The combination long double denotes a floating point type, which has the widest range out of the
three floating point types.
C++11
When the long specifier occurs twice, as in long long, it denotes a signed integer type that is at
least as long as long, and whose range includes at least -9223372036854775807 to
https://riptutorial.com/ 41
+9223372036854775807, inclusive (that is, -(2^63 - 1) to +(2^63 - 1)).
short
Denotes a signed integer type that is at least as long as char, and whose range includes at least -
32767 to +32767, inclusive. This type can also be written as short int.
void
An incomplete type; it is not possible for an object to have type void, nor are there arrays of void or
references to void. It is used as the return type of functions that do not return anything.
Moreover, a function may redundantly be declared with a single parameter of type void; this is
equivalent to declaring a function with no parameters (e.g. int main() and int main(void) declare
the same function). This syntax is allowed for compatibility with C (where function declarations
have a different meaning than in C++).
The type void* ("pointer to void") has the property that any object pointer can be converted to it
and back and result in the same pointer. This feature makes the type void* suitable for certain
kinds of (type-unsafe) type-erasing interfaces, for example for generic contexts in C-style APIs
(e.g. qsort, pthread_create).
Any expression may be converted to an expression of type void; this is called a discarded-value
expression:
This may be useful to signal explicitly that the value of an expression is not of interest and that the
expression is to be evaluated for its side effects only.
wchar_t
An integer type large enough to represent all characters of the largest supported extended
character set, also known as the wide-character set. (It is not portable to make the assumption
that wchar_t uses any particular encoding, such as UTF-16.)
It is normally used when you need to store characters over ASCII 255 , as it has a greater size
than the character type char.
https://riptutorial.com/ 42
const wchar_t message_chinese[] = L" \n";// Chinese for "hello, world\n"
const wchar_t message_hebrew[] = L"\םלוע םולשn"; //Hebrew for "hello, world\n"
const wchar_t message_russian[] = L"Привет мир\n"; //Russian for "hello, world\n"
const wchar_t message_tamil[] = L"ஹலோ உலகம்\n"; //Tamil for "hello, world\n"
https://riptutorial.com/ 43
Chapter 11: Bit fields
Introduction
Bit fields tightly pack C and C++ structures to reduce size. This appears painless: specify the
number of bits for members, and compiler does the work of co-mingling bits. The restriction is
inability to take the address of a bit field member, since it is stored co-mingled. sizeof() is also
disallowed.
The cost of bit fields is slower access, as memory must be retrieved and bitwise operations
applied to extract or modify member values. These operations also add to executable size.
Remarks
How expensive are the bitwise operations? Suppose a simple non-bit field structure:
struct foo {
unsigned x;
unsigned y;
}
static struct foo my_var;
my_var.y = 5;
If sizeof (unsigned) == 4, then x is stored at the start of the structure, and y is stored 4 bytes in.
Assembly code generated may resemble:
This is straightforward because x is not co-mingled with y. But imagine redefining the structure
with bit fields:
struct foo {
unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
unsigned y : 4;
}
Both x and y will be allocated 4 bits, sharing a single byte. The structure thus takes up 1 byte,
instead of 8. Consider the assembly to set y now, assuming it ends up in the upper nibble:
https://riptutorial.com/ 44
stb register1[0],register2 ; put the modified byte back into memory
This may be a good trade-off if we have thousands or millions of these structures, and it helps
keeps memory in cache or prevents swapping—or could bloat the executable to worsen these
problems and slow processing. As with all things, use good judgement.
Device driver use: Avoid bit fields as a clever implementation strategy for device drivers. Bit field
storage layouts are not necessarily consistent between compilers, making such implementations
non-portable. The read-modify-write to set values may not do what devices expect, causing
unexpected behaviors.
Examples
Declaration and Usage
struct FileAttributes
{
unsigned int ReadOnly: 1;
unsigned int Hidden: 1;
};
Here, each of these two fields will occupy 1 bit in memory. It is specified by : 1 expression after
the variable names. Base type of bit field could be any integral type (8-bit int to 64-bit int). Using
unsigned type is recommended, otherwise surprises may come.
If more bits are required, replace "1" with number of bits required. For example:
struct Date
{
unsigned int Year : 13; // 2^13 = 8192, enough for "year" representation for long time
unsigned int Month: 4; // 2^4 = 16, enough to represent 1-12 month values.
unsigned int Day: 5; // 32
};
The whole structure is using just 22 bits, and with normal compiler settings, sizeof this structure
would be 4 bytes.
Usage is pretty simple. Just declare the variable, and use it like ordinary structure.
Date d;
d.Year = 2016;
d.Month = 7;
d.Day = 22;
https://riptutorial.com/ 45
Chapter 12: Bit Manipulation
Remarks
In order to use std::bitset you will have to include <bitset> header.
#include <bitset>
std::bitset overloads all of the operator functions to allow the same usage as the c-style handling
of bitsets.
References
Examples
Setting a bit
Using std::bitset
set(x) or set(x,true) - sets bit at position x to 1.
std::bitset<5> num(std::string("01100"));
num.set(0); // num is now 01101
num.set(2); // num is still 01101
num.set(4,true); // num is now 11110
Clearing a bit
C-style bit-manipulation
A bit can be cleared using the bitwise AND operator (&).
https://riptutorial.com/ 46
// Bit x will be cleared
number &= ~(1LL << x);
Using std::bitset
reset(x) or set(x,false) - clears the bit at position x.
std::bitset<5> num(std::string("01100"));
num.reset(2); // num is now 01000
num.reset(0); // num is still 01000
num.set(3,false); // num is now 00000
Toggling a bit
C-style bit-manipulation
A bit can be toggled using the XOR operator (^).
Using std::bitset
std::bitset<4> num(std::string("0100"));
num.flip(2); // num is now 0000
num.flip(0); // num is now 0001
num.flip(); // num is now 1110 (flips all bits)
Checking a bit
C-style bit-manipulation
The value of the bit can be obtained by shifting the number to the right x times and then
performing bitwise AND (&) on it:
(number >> x) & 1LL; // 1 if the 'x'th bit of 'number' is set, 0 otherwise
The right-shift operation may be implemented as either an arithmetic (signed) shift or a logical
(unsigned) shift. If number in the expression number >> x has a signed type and a negative value, the
resulting value is implementation-defined.
If we need the value of that bit directly in-place, we could instead left shift the mask:
https://riptutorial.com/ 47
(number & (1LL << x)); // (1 << x) if the 'x'th bit of 'number' is set, 0 otherwise
Either can be used as a conditional, since all non-zero values are considered true.
Using std::bitset
std::bitset<4> num(std::string("0010"));
bool bit_val = num.test(1); // bit_val value is set to true;
C-style bit-manipulation
// Bit n will be set if x is 1 and cleared if x is 0.
number ^= (-x ^ number) & (1LL << n);
Using std::bitset
set(n,val) - sets bit n to the value val.
std::bitset<5> num(std::string("00100"));
num.set(0,true); // num is now 00101
num.set(2,false); // num is now 00001
C-style bit-manipulation
x = -1; // -1 == 1111 1111 ... 1111b
(See here for an explanation of why this works and is actually the best approach.)
Using std::bitset
std::bitset<10> x;
x.set(); // Sets all bits to '1'
https://riptutorial.com/ 48
C-style bit-manipulation
template <typename T>
T rightmostSetBitRemoved(T n)
{
// static_assert(std::is_integral<T>::value && !std::is_signed<T>::value, "type should be
unsigned"); // For c++11 and later
return n & (n - 1);
}
Explanation
The population count of a bitstring is often needed in cryptography and other applications and the
problem has been widely studied.
It goes through as many iterations as there are set bits, so it's good when value is expected to
have few nonzero bits.
The method was first proposed by Peter Wegner (in CACM 3 / 322 - 1960) and it's well known
since it appears in C Programming Language by Brian W. Kernighan and Dennis M. Ritchie.
unsigned popcount(std::uint64_t x)
{
const std::uint64_t m1 = 0x5555555555555555; // binary: 0101...
const std::uint64_t m2 = 0x3333333333333333; // binary: 00110011..
const std::uint64_t m4 = 0x0f0f0f0f0f0f0f0f; // binary: 0000111100001111
https://riptutorial.com/ 49
x -= (x >> 1) & m1; // put count of each 2 bits into those 2 bits
x = (x & m2) + ((x >> 2) & m2); // put count of each 4 bits into those 4 bits
x = (x + (x >> 4)) & m4; // put count of each 8 bits into those 8 bits
return (x * h01) >> 56; // left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
}
This kind of implementation has the best worst-case behavior (see Hamming weight for further
details).
Many CPUs have a specific instruction (like x86's popcnt) and the compiler could offer a specific (
non standard) built in function. E.g. with g++ there is:
The n & (n - 1) trick (see Remove rightmost set bit) is also useful to determine if an integer is a
power of 2:
Note that without the first part of the check (n &&), 0 is incorrectly considered a power of 2.
One of several applications of bit manipulation is converting a letter from small to capital or vice
versa by choosing a mask and a proper bit operation. For example, the a letter has this binary
representation 01(1)00001 while its capital counterpart has 01(0)00001. They differ solely in the bit in
parenthesis. In this case, converting the a letter from small to capital is basically setting the bit in
parenthesis to one. To do so, we do the following:
/****************************************
convert small letter to captial letter.
========================================
a: 01100001
mask: 11011111 <-- (0xDF) 11(0)11111
:---------
a&mask: 01000001 <-- A letter
*****************************************/
#include <cstdio>
int main()
{
char op1 = 'a'; // "a" letter (i.e. small case)
int mask = 0xDF; // choosing a proper mask
https://riptutorial.com/ 50
printf("a (AND) mask = A\n");
printf("%c & 0xDF = %c\n", op1, op1 & mask);
return 0;
}
The result is
https://riptutorial.com/ 51
Chapter 13: Bit Operators
Remarks
Bit shift operations are not portable across all processor architectures, different processors can
have different bit-widths. In other words, if you wrote
int a = ~0;
int b = a << 1;
This value would be different on a 64 bit machine vs. on a 32 bit machine, or from an x86 based
processor to a PIC based processor.
Endian-ness does not need to be taken into account for the bit wise operations themselves, that is,
the right shift (>>) will shift the bits towards the least significant bit and an XOR will perform an
exclusive or on the bits. Endian-ness only needs to be taken into account with the data itself, that
is, if endian-ness is a concern for your application, it's a concern regardless of bit wise operations.
Examples
& - bitwise AND
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
Output
a = 6, b = 10, c = 2
Why
A bit wise AND operates on the bit level and uses the following Boolean truth table:
When the binary value for a (0110) and the binary value for b (1010) are AND'ed together we get the
binary value of 0010:
int a = 0 1 1 0
int b = 1 0 1 0 &
---------
int c = 0 0 1 0
https://riptutorial.com/ 52
The bit wise AND does not change the value of the original values unless specifically assigned to
using the bit wise assignment compound operator &=:
| - bitwise OR
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
Output
a = 5, b = 12, c = 13
Why
A bit wise OR operates on the bit level and uses the following Boolean truth table:
When the binary value for a (0101) and the binary value for b (1100) are OR'ed together we get the
binary value of 1101:
int a = 0 1 0 1
int b = 1 1 0 0 |
---------
int c = 1 1 0 1
The bit wise OR does not change the value of the original values unless specifically assigned to
using the bit wise assignment compound operator |=:
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
Output
a = 5, b = 9, c = 12
https://riptutorial.com/ 53
Why
A bit wise XOR (exclusive or) operates on the bit level and uses the following Boolean truth table:
Notice that with an XOR operation true OR true = false where as with operations true AND/OR true
= true, hence the exclusive nature of the XOR operation.
Using this, when the binary value for a (0101) and the binary value for b (1001) are XOR'ed together
we get the binary value of 1100:
int a = 0 1 0 1
int b = 1 0 0 1 ^
---------
int c = 1 1 0 0
The bit wise XOR does not change the value of the original values unless specifically assigned to
using the bit wise assignment compound operator ^=:
The bit wise XOR can be utilized in many ways and is often utilized in bit mask operations for
encryption and compression.
Note: The following example is often shown as an example of a nice trick. But should not be used
in production code (there are better ways std::swap() to achieve the same result).
You can also utilize an XOR operation to swap two variables without a temporary:
int a = 42;
int b = 64;
// XOR swap
a ^= b;
b ^= a;
a ^= b;
std::cout << "a = " << a << ", b = " << b << "\n";
To productionalize this you need to add a check to make sure it can be used.
https://riptutorial.com/ 54
a ^= b;
b ^= a;
a ^= b;
}
}
So though it looks like a nice trick in isolation it is not useful in real code. xor is not a base logical
operation,but a combination of others: a^c=~(a&c)&(a|c)
int cn=0b0111;
Output
a = 234, b = 21
Why
A bit wise NOT (unary complement) operates on the bit level and simply flips each bit. If it's a 1, it's
changed to a 0, if it's a 0, it's changed to a 1. The bit wise NOT has the same effect as XOR'ing a
value against the max value for a specific type:
The bit wise NOT can also be a convenient way to check the maximum value for a specific integral
type:
The bit wise NOT does not change the value of the original value and does not have a compound
assignment operator, so you can not do a ~= 10 for example.
The bit wise NOT (~) should not be confused with the logical NOT (!); where a bit wise NOT will
flip each bit, a logical NOT will use the whole value to do its operation on, in other words (!1) !=
(~1)
https://riptutorial.com/ 55
<< - left shift
int a = 1; // 0001b
int b = a << 1; // 0010b
std::cout << "a = " << a << ", b = " << b << std::endl;
Output
a = 1, b = 2
Why
The left bit wise shift will shift the bits of the left hand value (a) the number specified on the right (1
), essentially padding the least significant bits with 0's, so shifting the value of 5 (binary 0000 0101)
to the left 4 times (e.g. 5 << 4) will yield the value of 80 (binary 0101 0000). You might note that
shifting a value to the left 1 time is also the same as multiplying the value by 2, example:
int a = 7;
while (a < 200) {
std::cout << "a = " << a << std::endl;
a <<= 1;
}
a = 7;
while (a < 200) {
std::cout << "a = " << a << std::endl;
a *= 2;
}
But it should be noted that the left shift operation will shift all bits to the left, including the sign bit,
example:
int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1; // 1111 1111 1111 1111 1111 1111 1111 1110
std::cout << "a = " << a << ", b = " << b << std::endl;
While some compilers will yield results that seem expected, it should be noted that if you left shift
a signed number so that the sign bit is affected, the result is undefined. It is also undefined if the
number of bits you wish to shift by is a negative number or is larger than the number of bits the
type on the left can hold, example:
int a = 1;
int b = a << -1; // undefined behavior
char c = a << 20; // undefined behavior
The bit wise left shift does not change the value of the original values unless specifically assigned
to using the bit wise assignment compound operator <<=:
https://riptutorial.com/ 56
int a = 5; // 0101b
a <<= 1; // a = a << 1;
int a = 2; // 0010b
int b = a >> 1; // 0001b
std::cout << "a = " << a << ", b = " << b << std::endl;
Output
a = 2, b = 1
Why
The right bit wise shift will shift the bits of the left hand value (a) the number specified on the right (
1); it should be noted that while the operation of a right shift is standard, what happens to the bits
of a right shift on a signed negative number is implementation defined and thus cannot be
guaranteed to be portable, example:
int a = -2;
int b = a >> 1; // the value of b will be depend on the compiler
It is also undefined if the number of bits you wish to shift by is a negative number, example:
int a = 1;
int b = a >> -1; // undefined behavior
The bit wise right shift does not change the value of the original values unless specifically
assigned to using the bit wise assignment compound operator >>=:
int a = 2; // 0010b
a >>= 1; // a = a >> 1;
https://riptutorial.com/ 57
Chapter 14: Build Systems
Introduction
C++, like C, has a long and varied history regarding compilation workflows and build processes.
Today, C++ has various popular build systems that are used to compile programs, sometimes for
multiple platforms within one build system. Here, a few build systems will be reviewed and
analyzed.
Remarks
Currently, there exists no universal or dominant build system for C++ that is both popular and
cross-platform. However, there do exist several major build systems that are attached to major
platforms/projects, the most notable being GNU Make with the GNU/Linux operating system and
NMAKE with the Visual C++/Visual Studio project system.
Additionally, some Integrated Development Environments (IDEs) also include specialized build
systems to be used specifically with the native IDE. Certain build system generators can generate
these native IDE build system/project formats, such as CMake for Eclipse and Microsoft Visual
Studio 2012.
Examples
Generating Build Environment with CMake
CMake generates build environments for nearly any compiler or IDE from a single project
definition. The following examples will demonstrate how to add a CMake file to the cross-platform
"Hello World" C++ code.
CMake files are always named "CMakeLists.txt" and should already exist in every project's root
directory (and possibly in sub-directories too.) A basic CMakeLists.txt file looks like:
cmake_minimum_required(VERSION 2.4)
project(HelloWorld)
add_executable(HelloWorld main.cpp)
This file tells CMake the project name, what file version to expect, and instructions to generate an
executable called "HelloWorld" that requires main.cpp.
Generate a build environment for your installed compiler/IDE from the command line:
> cmake .
https://riptutorial.com/ 58
Build the application with:
This generates the default build environment for the system, depending on the OS and installed
tools. Keep source code clean from any build artifacts with use of "out-of-source" builds:
CMake can also abstract the platform shell's basic commands from the previous example:
CMake includes generators for a number of common build tools and IDEs. To generate makefiles
for Visual Studio's nmake:
Introduction
The GNU Make (styled make) is a program dedicated to the automation of executing shell
commands. GNU Make is one specific program that falls under the Make family. Make remains
popular among Unix-like and POSIX-like operating systems, including those derived from the
Linux kernel, Mac OS X, and BSD.
GNU Make is especially notable for being attached to the GNU Project, which is attached to the
popular GNU/Linux operating system. GNU Make also has compatible versions running on various
flavors of Windows and Mac OS X. It is also a very stable version with historical significance that
remains popular. It is for these reasons that GNU Make is often taught alongside C and C++.
Basic rules
To compile with make, create a Makefile in your project directory. Your Makefile could be as
simple as:
Makefile
https://riptutorial.com/ 59
# First, we set the compiler to be g++
CXX=g++
# Then, we say that we want to compile with g++'s recommended warnings and some extra ones.
CXXFLAGS=-Wall -Wextra -pedantic
SRCS=main.cpp
# When you call `make` at the command line, this "target" is called.
# The $(EXE) at the right says that the `all` target depends on the `$(EXE)` target.
# $(EXE) expands to be the content of the EXE variable
# Note: Because this is the first target, it becomes the default target if `make` is called
without target
all: $(EXE)
NOTE: Make absolutely sure that the indentations are with a tab, not with four
spaces. Otherwise, you'll get an error of Makefile:10: *** missing separator. Stop.
$ cd ~/Path/to/project
$ make
$ ls
app main.cpp Makefile
$ ./app
Hello World!
$ make clean
$ ls
main.cpp Makefile
Incremental builds
When you start having more files, make becomes more useful. What if you edited a.cpp but not
b.cpp? Recompiling b.cpp would take more time.
https://riptutorial.com/ 60
With the following directory structure:
.
+-- src
| +-- a.cpp
| +-- a.hpp
| +-- b.cpp
| +-- b.hpp
+-- Makefile
Makefile
CXX=g++
CXXFLAGS=-Wall -Wextra -pedantic
EXE=app
SRCS_GLOB=src/*.cpp
SRCS=$(wildcard $(SRCS_GLOB))
OBJS=$(SRCS:.cpp=.o)
all: $(EXE)
$(EXE): $(OBJS)
@$(CXX) -o $@ $(OBJS)
depend: .depend
.depend: $(SRCS)
@-rm -f ./.depend
@$(CXX) $(CXXFLAGS) -MM $^>>./.depend
clean:
-rm -f $(EXE)
-rm $(OBJS)
-rm *~
-rm .depend
include .depend
Again watch the tabs. This new Makefile ensures that you only recompile changed files,
minimizing compile time.
Documentation
For more on make, see the official documentation by the Free Software Foundation, the
stackoverflow documentation and dmckee's elaborate answer on stackoverflow.
You can build the cross-platform "Hello World" C++ code, using Scons - A Python-language
software construction tool.
https://riptutorial.com/ 61
First, create a file called SConstruct (note that SCons will look for a file with this exact name by
default). For now, the file should be in a directory right along your hello.cpp. Write in the new file
the line
Program('hello.cpp')
Now, from the terminal, run scons. You should see something like
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o hello.o -c hello.cpp
g++ -o hello hello.o
scons: done building targets.
(although the details will vary depending on your operating system and installed compiler).
The Environment and Glob classes will help you further configure what to build. E.g., the SConstruct
file
env=Environment(CPPPATH='/usr/include/boost/',
CPPDEFINES=[],
LIBS=[],
SCONS_CXX_STANDARD="c++11"
)
env.Program('hello', Glob('src/*.cpp'))
builds the executable hello, using all cpp files in src. Its CPPPATH is /usr/include/boost and it
specifies the C++11 standard.
Ninja
Introduction
The Ninja build system is described by its project website as "a small build system with a focus on
speed." Ninja is designed to have its files generated by build system file generators, and takes a
low-level approach to build systems, in contrast to higher-level build system managers like CMake
or Meson.
Ninja is primarily written in C++ and Python, and was created as an alternative to the SCons build
system for the Chromium project.
Introduction
https://riptutorial.com/ 62
NMAKE is a command-line utility developed by Microsoft to be used primarily in conjunction with
Microsoft Visual Studio and/or the Visual C++ command line tools.
NMAKE is build system that falls under the Make family of build systems, but has certain distinct
features that diverge from Unix-like Make programs, such as supporting Windows-specific file path
syntax (which itself differs from Unix-style file paths).
Autotools (GNU)
Introduction
The Autotools are a group of programs that create a GNU Build System for a given software
package. It is a suite of tools that work together to produce various build resources, such as a
Makefile (to be used with GNU Make). Thus, Autotools can be considered a de facto build system
generator.
• Autoconf
• Automake (not to be confused with make)
In general, Autotools is meant to generate the Unix-compatible script and Makefile to allow the
following command to build (as well as install) most packages (in the simple case):
As such, Autotools also has a relationship with certain package managers, especially those that
are attached to operating systems that conform to the POSIX Standard(s).
https://riptutorial.com/ 63
Chapter 15: C incompatibilities
Introduction
This describes what C code will break in a C++ compiler.
Examples
Reserved Keywords
The first example are keywords that have a special purpose in C++: the following is legal in C, but
not C++.
int class = 5
In C, pointers can be cast to a void*, which needs an explicit cast in C++. The following is illegal in
C++, but legal in C:
void* ptr;
int* intptr = ptr;
Adding an explicit cast makes this work, but can cause further issues.
goto or switch
In C++, you may not skip initializations with goto or switch. The following is valid in C, but not C++:
goto foo;
int skipped = 1;
foo;
https://riptutorial.com/ 64
Chapter 16: C++ Containers
Introduction
C++ containers store a collection of elements. Containers include vectors, lists, maps, etc. Using
Templates, C++ containers contain collections of primitives (e.g. ints) or custom classes (e.g.
MyClass).
Examples
C++ Containers Flowchart
Choosing which C++ Container to use can be tricky, so here's a simple flowchart to help decide
which Container is right for the job.
https://riptutorial.com/ 65
https://riptutorial.com/ 66
Megan Hopkins
https://riptutorial.com/ 67
Chapter 17: C++ Debugging and Debug-
prevention Tools & Techniques
Introduction
A lot of time from C++ developers is spent debugging. This topic is meant to assist with this task
and give inspiration for techniques. Don't expect an extensive list of issues and solutions fixed by
the tools or a manual on the mentioned tools.
Remarks
This topic ain't complete yet, examples on following techniques/tools would be useful:
Examples
My C++ program ends with segfault - valgrind
#include <iostream>
void fail() {
int *p1;
int *p2(NULL);
int *p3 = p1;
if (p3) {
std::cout << *p3 << std::endl;
}
}
int main() {
fail();
}
Run:
$ ./main
https://riptutorial.com/ 68
Segmentation fault (core dumped)
$
$ valgrind ./main
==8515== Memcheck, a memory error detector
==8515== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8515== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==8515== Command: ./main
==8515==
==8515== Conditional jump or move depends on uninitialised value(s)
==8515== at 0x400813: fail() (main.cpp:7)
==8515== by 0x40083F: main (main.cpp:13)
==8515==
==8515== Invalid read of size 4
==8515== at 0x400819: fail() (main.cpp:8)
==8515== by 0x40083F: main (main.cpp:13)
==8515== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==8515==
==8515==
==8515== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==8515== Access not within mapped region at address 0x0
==8515== at 0x400819: fail() (main.cpp:8)
==8515== by 0x40083F: main (main.cpp:13)
==8515== If you believe this happened as a result of a stack
==8515== overflow in your program's main thread (unlikely but
==8515== possible), you can try to increase the size of the
==8515== main thread stack using the --main-stacksize= flag.
==8515== The main thread stack size used in this run was 8388608.
==8515==
==8515== HEAP SUMMARY:
==8515== in use at exit: 72,704 bytes in 1 blocks
==8515== total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==8515==
==8515== LEAK SUMMARY:
==8515== definitely lost: 0 bytes in 0 blocks
==8515== indirectly lost: 0 bytes in 0 blocks
==8515== possibly lost: 0 bytes in 0 blocks
==8515== still reachable: 72,704 bytes in 1 blocks
==8515== suppressed: 0 bytes in 0 blocks
==8515== Rerun with --leak-check=full to see details of leaked memory
==8515==
==8515== For counts of detected and suppressed errors, rerun with: -v
==8515== Use --track-origins=yes to see where uninitialised values come from
==8515== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
$
The first line tells us that segfault is caused by reading 4 bytes. The second and the third lines are
call stack. It means that the invalid read is performed at the fail() function, line 8 of main.cpp,
https://riptutorial.com/ 69
which is called by main, line 13 of main.cpp.
But we check the pointer first, so what's wrong? Lets check the other block:
if (p3) {
Which points us to the line where we check p3 instead of p2. But how is it possible that p3 is
uninitialized? We initialize it by:
The argument for valgrind is just after valgrind. If we put it after our program, it would be passed to
our program.
Which tells us that the uninitialized value we used at line 7 was created at line 3:
int *p1;
#include <iostream>
void fail() {
https://riptutorial.com/ 70
int *p1;
int *p2(NULL);
int *p3 = p1;
if (p3) {
std::cout << *p2 << std::endl;
}
}
int main() {
fail();
}
gdb ./main
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/opencog/code-snippets/stackoverflow/a.out
We see the segmentation fault is happening at line 11. So the only variable being used at this line
is pointer p2. Lets examine its content typing print.
(gdb) print p2
$1 = (int *) 0x0
Now we see that p2 was initialized to 0x0 which stands for NULL. At this line, we know that we are
trying to dereference a NULL pointer. So we go and fix it.
Clean code
Debugging starts with understanding the code you are trying to debug.
Bad code:
int main() {
int value;
std::vector<int> vectorToSort;
vectorToSort.push_back(42); vectorToSort.push_back(13);
for (int i = 52; i; i = i - 1)
{
https://riptutorial.com/ 71
vectorToSort.push_back(i *2);
}
/// Optimized for sorting small vectors
if (vectorToSort.size() == 1);
else
{
if (vectorToSort.size() <= 2)
std::sort(vectorToSort.begin(), std::end(vectorToSort));
}
for (value : vectorToSort) std::cout << value << ' ';
return 0; }
Better code:
std::vector<int> createSemiRandomData() {
std::vector<int> data;
data.push_back(42);
data.push_back(13);
for (int i = 52; i; --i)
vectorToSort.push_back(i *2);
return data;
}
std::sort(vectorToSort.begin(), vectorToSort.end());
}
int main() {
auto vectorToSort = createSemiRandomData();
sortVector(std::ref(vectorToSort));
printVector(vectorToSort);
return 0;
}
Regardless of the coding styles you prefer and use, having a consistent coding (and formatting)
style will help you understanding the code.
Looking at the code above, one can identify a couple of improvements to improve readability and
debuggability:
https://riptutorial.com/ 72
of the data and only want to step into the sorting.
Another advantage is that you need to read less code (and memorize it) while stepping through
the code. You now only need to read 3 lines of code in main() in order to understand it, instead of
the whole function.
The third advantage is that you simply have less code to look at, which helps a trained eye in
spotting this bug within seconds.
As formatting code is time consuming task, it is recommended to use a dedicated tool for this.
Most IDEs have at least some kind of support for this and can do formatting more consistent than
humans.
You might note that the style is not limited to spaces and newlines as we no longer mix the free-
style and the member functions to get begin/end of the container. (v.begin() vs std::end(v)).
Conclusion
Having clean code will help you understanding the code and will reduce the time you need to
debug it. In the second example, a code reviewer might even spot the bug at first glance, while the
bug might be hidden in the details in the first one. (PS: The bug is in the compare with 2.)
Static analysis
Static analysis is the technique in which on checks the code for patterns linked to known bugs.
Using this technique is less time consuming than a code review, though, its checks are only limited
to those programmed in the tool.
Checks can include the incorrect semi-colon behind the if-statement (if (var);) till advanced
graph algorithms which determine if a variable is not initialized.
https://riptutorial.com/ 73
Compiler warnings
Enabling static analysis is easy, the most simplistic version is already build-in in your compiler:
If you enable these options, you will notice that each compiler will find bugs the others don't and
that you will get errors on techniques which might be valid or valid in a specific context. while
(staticAtomicBool); might be acceptable even if while (localBool); ain't.
So unlike code review, you are fighting a tool which understands your code, tells you a lot of useful
bugs and sometimes disagrees with you. In this last case, you might have to suppress the warning
locally.
As the options above enable all warnings, they might enable warnings you don't want. (Why
should your code be C++98 compatible?) If so, you can simply disable that specific warning:
Where compiler warnings assist you during development, they slow down compilation quite a bit.
That is why you might not always want to enable them by default. Either you run them by default
or you enable some continuous integration with the more expensive checks (or all of them).
External tools
If you decide to have some continuous integration, the use of other tools ain't such a stretch. A
tool like clang-tidy has an list of checks which covers a wide range of issues, some examples:
• Actual bugs
Prevention of slicing
○
• Readability checks
Misleading indentation
○
• Modernization checks
Use make_unique()
○
Use nullptr
○
• Performance checks
Find unneeded copies
○
The list might not be that large, as Clang already has a lot of compiler warnings, however it will
bring you one step closer to a high quality code base.
https://riptutorial.com/ 74
Other tools
Other tools with similar purpose exist, like:
Conclusion
A lot static analysis tools exist for C++, both build-in in the compiler as external tools. Trying them
out doesn't take that much time for easy setups and they will find bugs you might miss in code
review.
Stack corruptions are annoying bugs to look at. As the stack is corrupted, the debugger often can't
give you a good stack trace of where you are and how you got there.
This is where safe-stack comes into play. Instead of using a single stack for your threads, it will
use two: A safe stack and a dangerous stack. The safe stack works exactly like it did before,
except that some parts are moved to the dangerous stack.
As a result, any operation you do with those pointers, any modification you make on the memory
(based on those pointers/references) can only effect the memory in the second stack. As one
never gets a pointer which is close to the safe stack, the stack cannot corrupt the stack and the
debugger can still read all functions on the stack to give a nice trace.
For this reason, the feature has been activated on chromium and has been reported to have a
<1% CPU overhead.
https://riptutorial.com/ 75
Right now, the option is only available in the clang compiler, where one can pass -fsanitize=safe-
stack to the compiler. A proposal was made to implement the same feature in GCC.
Conclusion
Stack corruptions can become easier to debug when safe stack is enabled. Due to a low
performance overhead, you can even activated by default in your build configuration.
https://riptutorial.com/ 76
Chapter 18: C++ function "call by value" vs.
"call by reference"
Introduction
The scope of this section is to explain the differences in theory and implementation for what
happens with the parameters of a function upon calling.
In detail the parameters can be seen as variables before the function call and inside the function,
where the visible behaviour and accessibility to these variables differs with the method used to
hand them over.
Additionally, the reusability of variables and their respective values after the function call also is
explained by this topic.
Examples
Call by value
Upon calling a function there are new elements created on the program stack. These include
some information about the function and also space (memory locations) for the parameters and
the return value.
When handing over a parameter to a function the value of the used variable (or literal) is copied
into the memory location of the function parameter. This implies that now there a two memory
locations with the same value. Inside of the function we only work on the parameter memory
location.
After leaving the function the memory on the program stack is popped (removed) which erases all
data of the function call, including the memory location of the parameters we used inside. Thus,
the values changed inside the function do not affect the outside variables values.
int main(void) {
int a = 0;
int b = 1; //outer_b
int c;
https://riptutorial.com/ 77
c = func(a,b);
//the return value is copied to c
In this code we create variables inside the main function. These get assigned values. Upon calling
the functions there are two new variables created: f and inner_b where b shares the name with the
outer variable it does not share the memory location. The behaviour of a<->f and b<->b is identical.
The following graphic symbolizes what is happening on the stack and why there is no change in
varibale b. The graphic is not fully accurate but emphazises the example.
It is called "call by value" because we do not hand over the variables but only the values of these
variables.
https://riptutorial.com/ 78
Chapter 19: C++ Streams
Remarks
Default constructor of std::istream_iterator constructs an iterator which represents the end of the
stream. Thus, std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(), ....
means to copy from the current position in ifs to the end.
Examples
String streams
std::ostringstream is a class whose objects look like an output stream (that is, you can write to
them via operator<<), but actually store the writing results, and provide them in the form of a
stream.
#include <sstream>
#include <string>
int main()
{
ostringstream ss;
ss << "the answer to everything is " << 42;
const string result = ss.str();
}
The line
ostringstream ss;
creates such an object. This object is first manipulated like a regular stream:
Following that, though, the resulting stream can be obtained like this:
This is mainly useful when we have a class for which stream serialization has been defined, and
for which we want a string form. For example, suppose we have some class
https://riptutorial.com/ 79
class foo
{
// All sort of stuff here.
};
foo f;
we could use
ostringstream ss;
ss << f;
const string result = ss.str();
ifstreamhas operator bool(), which returns true when a stream has no errors and is ready to read.
Moreover, ifstream::operator >> returns a reference to the stream itself, so we can read and check
for EOF (as well as for errors) in one line with very elegant syntax:
std::ifstream ifs("1.txt");
std::string s;
while(ifs >> s) {
std::cout << s << std::endl;
}
https://riptutorial.com/ 80
while(std::getline(ifs, s)) {
std::cout << s << std::endl;
}
Obviously, std::getline should also be used for reading a single-line file till the end.
s.resize(100);
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
s.begin());
Otherwise, we need to insert each character to the end of the string, so std::back_inserter is what
we need:
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
std::back_inserter(s));
Alternatively, it is possible to initialize a collection with stream data, using a constructor with
iterator range arguments:
std::vector v(std::istreambuf_iterator<char>(ifs),
std::istreambuf_iterator<char>());
Note that these examples are also applicable if ifs is opened as binary file:
Copying streams
A file may be copied to another file with streams and iterators:
std::ofstream ofs("out.file");
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
std::ostream_iterator<char>(ofs));
ofs.close();
or redirected to any other type of stream with a compatible interface. For example Boost.Asio
network stream:
boost::asio::ip::tcp::iostream stream;
stream.connect("example.com", "http");
https://riptutorial.com/ 81
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
std::ostream_iterator<char>(stream));
stream.close();
Arrays
As iterators might be thought of as a generalization of pointers, STL containers in the examples
above may be replaced with native arrays. Here is how to parse numbers into array:
int arr[100];
std::copy(std::istream_iterator<char>(ifs), std::istream_iterator<char>(), arr);
Beware of buffer overflow, as arrays cannot be resized on-the-fly after they were allocated. For
example, if the code above will be fed with a file that contains more than 100 integer numbers, it
will attempt to write outside the array and run into undefined behavior.
Basic printing
std::ostream_iterator allows to print contents of an STL container to any output stream without
explicit loops. The second argument of std::ostream_iterator constructor sets the delimiter. For
example, the following code:
std::vector<int> v = {1,2,3,4};
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ! "));
will print
1 ! 2 ! 3 ! 4 !
and instantiate std::ostream_iterator with float, while the contained values remain int:
std::vector<int> v = {1,2,3,4};
std::copy(v.begin(), v.end(), std::ostream_iterator<float>(std::cout, " ! "));
https://riptutorial.com/ 82
so the code above yields
std::vector<int> v = {1,2,3,4,8,16};
we can easily print boolean value of "x is even" statement for each element:
Arrays
As in the section about reading text files, almost all these considerations may be applied to native
arrays. For example, let's print squared values from a native array:
Parsing files
https://riptutorial.com/ 83
Parsing files into STL containers
istream_iteratorsare very useful for reading sequences of numbers or other parsable data into
STL containers without explicit loops in the code.
std::vector<int> v(100);
std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(),
v.begin());
std::vector<int> v;
std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(),
std::back_inserter(v));
Note that the numbers in the input file may be divided by any number of any whitespace
characters and newlines.
std::string s;
double a, b;
while(ifs >> a >> b >> s) {
std::cout << a << " " << b << " " << s << std::endl;
}
Transformation
Any range-manipulating function may be used with std::istream_iterator ranges. One of them is
std::transform, which allows to process data on-the-fly. For example, let's read integer values,
multiply them by 3.14 and store the result into floating-point container:
std::vector<double> v(100);
std::transform(std::istream_iterator<int>(ifs), std::istream_iterator<int>(),
v.begin(),
https://riptutorial.com/ 84
[](int val) {
return val * 3.14;
});
https://riptutorial.com/ 85
Chapter 20: C++11 Memory Model
Remarks
Different threads trying to access the same memory location participate in a data race if at least
one of the operations is a modification (also known as store operation). These data races cause
undefined behavior. To avoid them one needs to prevent these threads from concurrently
executing such conflicting operations.
Synchronization primitives (mutex, critical section and the like) can guard such accesses. The
Memory Model introduced in C++11 defines two new portable ways to synchronize access to
memory in multi-threaded environment: atomic operations and fences.
Atomic Operations
It is now possible to read and write to given memory location by the use of atomic load and atomic
store operations. For convenience these are wrapped in the std::atomic<t> template class. This
class wraps a value of type t but this time loads and stores to the object are atomic.
The template is not available for all types. Which types are available is implementation specific,
but this usually includes most (or all) available integral types as well as pointer types. So that
std::atomic<unsigned> and std::atomic<std::vector<foo> *> should be available, while
std::atomic<std::pair<bool,char>> most probably wont be.
• All atomic operations can be performed concurrently from multiple threads without causing
undefined behavior.
• An atomic load will see either the initial value which the atomic object was constructed with,
or the value written to it via some atomic store operation.
• Atomic stores to the same atomic object are ordered the same in all threads. If a thread has
already seen the value of some atomic store operation, subsequent atomic load operations
will see either the same value, or the value stored by subsequent atomic store operation.
• Atomic read-modify-write operations allow atomic load and atomic store to happen without
other atomic store in between. For example one can atomically increment a counter from
multiple threads, and no increment will be lost regardless of the contention between the
threads.
• Atomic operations receive an optional std::memory_order parameter which defines what
additional properties the operation has regarding other memory locations.
std::memory_order Meaning
https://riptutorial.com/ 86
std::memory_order Meaning
These memory order tags allow three different memory ordering disciplines: sequential
consistency, relaxed, and release-acquire with its sibling release-consume.
Sequential Consistency
If no memory order is specified for an atomic operation, the order defaults to sequential
consistency. This mode can also be explicitly selected by tagging the operation with
std::memory_order_seq_cst.
With this order no memory operation can cross the atomic operation. All memory operations
sequenced before the atomic operation happen before the atomic operation and the atomic
operation happens before all memory operations that are sequenced after it. This mode is
probably the easiest one to reason about but it also leads to the greatest penalty to performance.
It also prevents all compiler optimizations that might otherwise try to reorder operations past the
atomic operation.
Relaxed Ordering
The opposite to sequential consistency is the relaxed memory ordering. It is selected with the
std::memory_order_relaxed tag. Relaxed atomic operation will impose no restrictions on other
memory operations. The only effect that remains, is that the operation is itself still atomic.
Release-Acquire Ordering
An atomic store operation can be tagged with std::memory_order_release and an atomic load
operation can be tagged with std::memory_order_acquire. The first operation is called (atomic)
store-release while the second is called (atomic) load-acquire.
When load-acquire sees the value written by a store-release the following happens: all store
operations sequenced before the store-release become visible to (happen before) load operations
that are sequenced after the load-acquire.
Atomic read-modify-write operations can also receive the cumulative tag std::memory_order_acq_rel
. This makes the atomic load portion of the operation an atomic load-acquire while the atomic
store portion becomes atomic store-release.
The compiler is not allowed to move store operations after an atomic store-release operation. It is
https://riptutorial.com/ 87
also not allowed to move load operations before atomic load-acquire (or load-consume).
Also note that there is no atomic load-release or atomic store-acquire. Attempting to create such
operations makes them relaxed operations.
Release-Consume Ordering
This combination is similar to release-acquire, but this time the atomic load is tagged with
std::memory_order_consume and becomes (atomic) load-consume operation. This mode is the same
as release-acquire with the only difference that among the load operations sequenced after the
load-consume only these depending on the value loaded by the load-consume are ordered.
Fences
Fences also allow memory operations to be ordered between threads. A fence is either a release
fence or acquire fence.
If a release fence happens before an acquire fence, then stores sequenced before the release
fence are visible to loads sequenced after the acquire fence. To guarantee that the release fence
happens before the acquire fence one may use other synchronization primitives including relaxed
atomic operations.
Examples
Need for Memory Model
int x, y;
bool ready = false;
void init()
{
x = 2;
y = 3;
ready = true;
}
void use()
{
if (ready)
std::cout << x + y;
}
One thread calls the init() function while another thread (or signal handler) calls the use()
function. One might expect that the use() function will either print 5 or do nothing. This may not
always be the case for several reasons:
• The CPU may reorder the writes that happen in init() so that the code that actually
executes might look like:
https://riptutorial.com/ 88
void init()
{
ready = true;
x = 2;
y = 3;
}
• The CPU may reorder the reads that happen in use() so that the actually executed code
might become:
void use()
{
int local_x = x;
int local_y = y;
if (ready)
std::cout << local_x + local_y;
}
• An optimizing C++ compiler may decide to reorder the program in similar way.
Such reordering cannot change the behavior of a program running in single thread because a
thread cannot interleave the calls to init() and use(). On the other hand in a multi-threaded
setting one thread may see part of the writes performed by the other thread where it may happen
that use() may see ready==true and garbage in x or y or both.
The C++ Memory Model allows the programmer to specify which reordering operations are
permitted and which are not, so that a multi-threaded program would also be able to behave as
expected. The example above can be rewritten in thread-safe way like this:
int x, y;
std::atomic<bool> ready{false};
void init()
{
x = 2;
y = 3;
ready.store(true, std::memory_order_release);
}
void use()
{
if (ready.load(std::memory_order_acquire))
std::cout << x + y;
}
Here init() performs atomic store-release operation. This not only stores the value true into ready,
but also tells the compiler that it cannot move this operation before write operations that are
sequenced before it.
The use() function does an atomic load-acquire operation. It reads the current value of ready and
also forbids the compiler from placing read operations that are sequenced after it to happen before
the atomic load-acquire.
These atomic operations also cause the compiler to put whatever hardware instructions are
https://riptutorial.com/ 89
needed to inform the CPU to refrain from the unwanted reorderings.
Because the atomic store-release is to the same memory location as the atomic load-acquire, the
memory model stipulates that if the load-acquire operation sees the value written by the store-
release operation, then all writes performed by init()'s thread prior to that store-release will be
visible to loads that use()'s thread executes after its load-acquire. That is if use() sees ready==true,
then it is guaranteed to see x==2 and y==3.
Note that the compiler and the CPU are still allowed to write to y before writing to x, and similarly
the reads from these variables in use() can happen in any order.
Fence example
The example above can also be implemented with fences and relaxed atomic operations:
int x, y;
std::atomic<bool> ready{false};
void init()
{
x = 2;
y = 3;
atomic_thread_fence(std::memory_order_release);
ready.store(true, std::memory_order_relaxed);
}
void use()
{
if (ready.load(std::memory_order_relaxed))
{
atomic_thread_fence(std::memory_order_acquire);
std::cout << x + y;
}
}
If the atomic load operation sees the value written by the atomic store then the store happens
before the load, and so do the fences: the release fence happens before the acquire fence making
the writes to x and y that precede the release fence to become visible to the std::cout statement
that follows the acquire fence.
A fence might be beneficial if it can reduce the overall number of acquire, release or other
synchronization operations. For example:
void block_and_use()
{
while (!ready.load(std::memory_order_relaxed))
;
atomic_thread_fence(std::memory_order_acquire);
std::cout << x + y;
}
The block_and_use() function spins until the ready flag is set with the help of relaxed atomic load.
Then a single acquire fence is used to provide the needed memory ordering.
https://riptutorial.com/ 90
Read C++11 Memory Model online: https://riptutorial.com/cplusplus/topic/7975/cplusplus11-
memory-model
https://riptutorial.com/ 91
Chapter 21: Callable Objects
Introduction
Callable objects are the collection of all C++ structures which can be used as a function. In
practice, this are all things you can pass to the C++17 STL function invoke() or which can be used
in the constructor of std::function, this includes: Function pointers, Classes with operator(),
Classes with implicit conversions, References to functions, Pointers to member functions, Pointers
to member data, lambdas. The callable objects are used in many STL algorithms as predicate.
Remarks
A very useful talk by Stephan T. Lavavej (<functional>: What's New, And Proper Use) (Slides)
leads to the base of this documentation.
Examples
Function Pointers
Function pointers are the most basic way of passing functions around, which can also be used in
C. (See the C documentation for more details).
For the purpose of callable objects, a function pointer can be defined as:
If we would be using a function pointer for writing our own vector sort, it would look like:
struct GreaterThanInt {
static bool cmp(int lhs, int rhs) { return lhs > rhs; }
};
https://riptutorial.com/ 92
sortVectorInt(vectorOfInt, &GreaterThanInt::cmp); // Passes the pointer to a static member
function
Alternatively, we could have invoked the function pointer one of following ways:
Every class which overloads the operator() can be used as a function object. These classes can
be written by hand (often referred to as functors) or automatically generated by the compiler by
writing Lambdas from C++11 on.
struct Person {
std::string name;
unsigned int age;
};
As functors have their own identity, they cannot be put in a typedef and these have to be accepted
via template argument. The definition of std::find_if can look like:
From C++17 on, the calling of the predicate can be done with invoke: std::invoke(predicate, *i).
https://riptutorial.com/ 93
Chapter 22: Classes/Structures
Syntax
• variable.member_var = constant;
• variable.member_function();
• variable_pointer->member_var = constant;
• variable_pointer->member_function();
Remarks
Note that the only difference between the struct and class keywords is that by default, the
member variables, member functions, and base classes of a struct are public, while in a class
they are private. C++ programmers tend to call it a class if it has constructors and destructors, and
the ability to enforce its own invariants; or a struct if it's just a simple collection of values, but the
C++ language itself makes no distinction.
Examples
Class basics
A class is a user-defined type. A class is introduced with the class, struct or union keyword. In
colloquial usage, the term "class" usually refers only to non-union classes.
The class and struct keywords, called class keys, are largely interchangeable, except that the
default access specifier for members and bases is "private" for a class declared with the class key
and "public" for a class declared with the struct or union key (cf. Access modifiers).
struct Vector
{
int x;
int y;
int z;
};
// are equivalent to
class Vector
{
public:
https://riptutorial.com/ 94
int x;
int y;
int z;
};
By declaring a class` a new type is added to your program, and it is possible to instantiate objects
of that class by
Vector my_vector;
my_vector.x = 10;
my_vector.y = my_vector.x + 1; // my_vector.y = 11;
my_vector.z = my_vector.y - 4; // my:vector.z = 7;
Access specifiers
There are three keywords that act as access specifiers. These limit the access to class members
following the specifier, until another specifier changes the access level again:
Keyword Description
protected Only the class itself, derived classes and friends have access
When the type is defined using the class keyword, the default access specifier is private, but if the
type is defined using the struct keyword, the default access specifier is public:
MyStruct s;
s.x = 9; // well formed, because x is public
MyClass c;
c.x = 9; // ill-formed, because x is private
Access specifiers are mostly used to limit access to internal fields and methods, and force the
programmer to use a specific interface, for example to force use of getters and setters instead of
referencing a variable directly:
class MyClass {
public: /* Methods: */
https://riptutorial.com/ 95
void setX(int const x) noexcept { m_x = x; }
private: /* Fields: */
int m_x;
};
Using protected is useful for allowing certain functionality of the type to be only accessible to the
derived classes, for example, in the following code, the method calculateValue() is only accessible
to classes deriving from the base class Plus2Base, such as FortyTwo:
struct Plus2Base {
int value() noexcept { return calculateValue() + 2; }
protected: /* Methods: */
virtual int calculateValue() noexcept = 0;
};
struct FortyTwo: Plus2Base {
protected: /* Methods: */
int calculateValue() noexcept final override { return 40; }
};
Note that the friend keyword can be used to add access exceptions to functions or types for
accessing protected and private members.
The public, protected, and private keywords can also be used to grant or limit access to base
class subobjects. See the Inheritance example.
Inheritance
If a class/struct B inherits from a class/struct A, this means that B has as a parent A. We say that B is
a derived class/struct from A, and A is the base class/struct.
struct A
{
public:
int p1;
protected:
int p2;
private:
int p3;
};
• public
• private
https://riptutorial.com/ 96
• protected
Note that the default inheritance is the same as the default visibility of members: public if you use
the struct keyword, and private for the class keyword.
It's even possible to have a class derive from a struct (or vice versa). In this case, the default
inheritance is controlled by the child, so a struct that derives from a class will default to public
inheritance, and a class that derives from a struct will have private inheritance by default.
public inheritance:
B b;
b.p1 = 1; //well formed, p1 is public
b.p2 = 1; //ill formed, p2 is protected
b.p3 = 1; //ill formed, p3 is inaccessible
private inheritance:
struct B : private A
{
void foo()
{
p1 = 0; //well formed, p1 is private in B
p2 = 0; //well formed, p2 is private in B
p3 = 0; //ill formed, p3 is private in A
}
};
B b;
b.p1 = 1; //ill formed, p1 is private
b.p2 = 1; //ill formed, p2 is private
b.p3 = 1; //ill formed, p3 is inaccessible
protected inheritance:
struct B : protected A
{
void foo()
{
p1 = 0; //well formed, p1 is protected in B
p2 = 0; //well formed, p2 is protected in B
p3 = 0; //ill formed, p3 is private in A
}
};
B b;
https://riptutorial.com/ 97
b.p1 = 1; //ill formed, p1 is protected
b.p2 = 1; //ill formed, p2 is protected
b.p3 = 1; //ill formed, p3 is inaccessible
Note that although protected inheritance is allowed, the actual use of it is rare. One instance of
how protected inheritance is used in application is in partial base class specialization (usually
referred to as "controlled polymorphism").
When OOP was relatively new, (public) inheritance was frequently said to model an "IS-A"
relationship. That is, public inheritance is correct only if an instance of the derived class is also an
instance of the base class.
This was later refined into the Liskov Substitution Principle: public inheritance should only be used
when/if an instance of the derived class can be substituted for an instance of the base class under
any possible circumstance (and still make sense).
Private inheritance is typically said to embody a completely different relationship: "is implemented
in terms of" (sometimes called a "HAS-A" relationship). For example, a Stack class could inherit
privately from a Vector class. Private inheritance bears a much greater similarity to aggregation
than to public inheritance.
Protected inheritance is almost never used, and there's no general agreement on what sort of
relationship it embodies.
Virtual Inheritance
struct A{};
struct B: public virtual A{};
When class B has virtual base A it means that A will reside in most derived class of inheritance
tree, and thus that most derived class is also responsible for initializing that virtual base:
struct A
{
int member;
A(int param)
{
member = param;
}
};
struct B: virtual A
{
B(): A(5){}
};
struct C: B
{
C(): /*A(88)*/ {}
};
https://riptutorial.com/ 98
void f()
{
C object; //error since C is not initializing it's indirect virtual base `A`
}
If we un-comment /*A(88)*/ we won't get any error since C is now initializing it's indirect virtual
base A.
Also note that when we're creating variable object, most derived class is C, so C is responsible for
creating(calling constructor of) A and thus value of A::member is 88, not 5 (as it would be if we were
creating object of type B).
A A A
/ \ | |
B C B C
\ / \ /
D D
virtual inheritance normal inheritance
B and C both inherit from A, and D inherits from B and C, so there are 2 instances of A in D! This
results in ambiguity when you're accessing member of A through D, as the compiler has no way of
knowing from which class do you want to access that member (the one which B inherits, or the one
that is inherited byC?).
Virtual inheritance solves this problem: Since virtual base resides only in most derived object,
there will be only one instance of A in D.
struct A
{
void foo() {}
};
Multiple Inheritance
class A {};
https://riptutorial.com/ 99
class B : public A {};
class A {};
class B {};
class C : public A, public B {};
Note: this can lead to ambiguity if the same names are used in multiple inherited classs or
structs. Be careful!
Multiple inheritance may be helpful in certain cases but, sometimes odd sort of problem
encounters while using multiple inheritance.
For example: Two base classes have functions with same name which is not overridden in derived
class and if you write code to access that function using object of derived class, compiler shows
error because, it cannot determine which function to call. Here is a code for this type of ambiguity
in multiple inheritance.
class base1
{
public:
void funtion( )
{ //code for base1 function }
};
class base2
{
void function( )
{ // code for base2 function }
};
};
int main()
{
derived obj;
But, this problem can be solved using scope resolution function to specify which function to class
either base1 or base2:
int main()
{
https://riptutorial.com/ 100
obj.base1::function( ); // Function of class base1 is called.
obj.base2::function( ); // Function of class base2 is called.
}
To access member variables and member functions of an object of a class, the . operator is used:
struct SomeStruct {
int a;
int b;
void foo() {}
};
SomeStruct var;
// Accessing member variable a in var.
std::cout << var.a << std::endl;
// Assigning member variable b in var.
var.b = 1;
// Calling a member function.
var.foo();
When accessing the members of a class via a pointer, the -> operator is commonly used.
Alternatively, the instance can be dereferenced and the . operator used, although this is less
common:
struct SomeStruct {
int a;
int b;
void foo() {}
};
SomeStruct var;
SomeStruct *p = &var;
// Accessing member variable a in var via pointer.
std::cout << p->a << std::endl;
std::cout << (*p).a << std::endl;
// Assigning member variable b in var via pointer.
p->b = 1;
(*p).b = 1;
// Calling a member function via a pointer.
p->foo();
(*p).foo();
When accessing static class members, the :: operator is used, but on the name of the class
instead of an instance of it. Alternatively, the static member can be accessed from an instance or a
pointer to an instance using the . or -> operator, respectively, with the same syntax as accessing
non-static members.
struct SomeStruct {
int a;
int b;
void foo() {}
static int c;
https://riptutorial.com/ 101
static void bar() {}
};
int SomeStruct::c;
SomeStruct var;
SomeStruct* p = &var;
// Assigning static member variable c in struct SomeStruct.
SomeStruct::c = 5;
// Accessing static member variable c in struct SomeStruct, through var and p.
var.a = var.c;
var.b = p->c;
// Calling a static member function.
SomeStruct::bar();
var.bar();
p->bar();
Background
The -> operator is needed because the member access operator . has precedence over the
dereferencing operator *.
One would expect that *p.a would dereference p (resulting in a reference to the object p is pointing
to) and then accessing its member a. But in fact, it tries to access the member a of p and then
dereference it. I.e. *p.a is equivalent to *(p.a). In the example above, this would result in a
compiler error because of two facts: First, p is a pointer and does not have a member a. Second, a
is an integer and, thus, can't be dereferenced.
The uncommonly used solution to this problem would be to explicitly control the precedence:
(*p).a
Instead, the -> operator is almost always used. It is a short-hand for first dereferencing the pointer
and then accessing it. I.e. (*p).a is exactly the same as p->a.
The :: operator is the scope operator, used in the same manner as accessing a member of a
namespace. This is because a static class member is considered to be in that class' scope, but
isn't considered a member of instances of that class. The use of normal . and -> is also allowed
for static members, despite them not being instance members, for historical reasons; this is of use
for writing generic code in templates, as the caller doesn't need to be concerned with whether a
given member function is static or non-static.
Private inheritance is useful when it is required to restrict the public interface of the class:
class A {
public:
int move();
int turn();
};
class B : private A {
public:
https://riptutorial.com/ 102
using A::turn;
};
B b;
b.move(); // compile error
b.turn(); // OK
This approach efficiently prevents an access to the A public methods by casting to the A pointer or
reference:
B b;
A& a = static_cast<A&>(b); // compile error
In the case of public inheritance such casting will provide access to all the A public methods
despite on alternative ways to prevent this in derived B, like hiding:
class B : public A {
private:
int move();
};
or private using:
class B : public A {
private:
using A::move;
};
B b;
A& a = static_cast<A&>(b); // OK for public inheritance
a.move(); // OK
C++11
Deriving a class may be forbidden with final specifier. Let's declare a final class:
class A final {
};
https://riptutorial.com/ 103
class A {
};
// OK.
class B final : public A {
};
Friendship
The friend keyword is used to give other classes and functions access to private and protected
members of the class, even through they are defined outside the class`s scope.
class Animal{
private:
double weight;
double height;
public:
friend void printWeight(Animal animal);
friend class AnimalPrinter;
// A common use for a friend function is to overload the operator<< for streaming.
friend std::ostream& operator<<(std::ostream& os, Animal animal);
};
class AnimalPrinter
{
public:
void print(const Animal& animal)
{
// Because of the `friend class AnimalPrinter;" declaration, we are
// allowed to access private members here.
std::cout << animal.weight << ", " << animal.height << std::endl;
}
}
int main() {
Animal animal = {10, 5};
printWeight(animal);
AnimalPrinter aPrinter;
aPrinter.print(animal);
https://riptutorial.com/ 104
10
10, 5
Animal height: 5
Nested Classes/Structures
A class or struct can also contain another class/struct definition inside itself, which is called a
"nested class"; in this situation, the containing class is referred to as the "enclosing class". The
nested class definition is considered to be a member of the enclosing class, but is otherwise
separate.
struct Outer {
struct Inner { };
};
From outside of the enclosing class, nested classes are accessed using the scope operator. From
inside the enclosing class, however, nested classes can be used without qualifiers:
struct Outer {
struct Inner { };
Inner in;
};
// ...
Outer o;
Outer::Inner i = o.in;
As with a non-nested class/struct, member functions and static variables can be defined either
within a nested class, or in the enclosing namespace. However, they cannot be defined within the
enclosing class, due to it being considered to be a different class than the nested class.
// Bad.
struct Outer {
struct Inner {
void do_something();
};
void Inner::do_something() {}
};
// Good.
struct Outer {
struct Inner {
void do_something();
};
};
void Outer::Inner::do_something() {}
As with non-nested classes, nested classes can be forward declared and defined later, provided
https://riptutorial.com/ 105
they are defined before being used directly.
class Outer {
class Inner1;
class Inner2;
Inner1 in1;
Inner2* in2p;
public:
Outer();
~Outer();
};
C++11
Prior to C++11, nested classes only had access to type names, static members, and enumerators
from the enclosing class; all other members defined in the enclosing class were off-limits.
C++11
As of C++11, nested classes, and members thereof, are treated as if they were friends of the
enclosing class, and can access all of its members, according to the usual access rules; if
members of the nested class require the ability to evaluate one or more non-static members of the
enclosing class, they must therefore be passed an instance:
class Outer {
struct Inner {
int get_sizeof_x() {
return sizeof(x); // Legal (C++11): x is unevaluated, so no instance is required.
}
int get_x() {
return x; // Illegal: Can't access non-static member without an instance.
}
int get_x(Outer& o) {
return o.x; // Legal (C++11): As a member of Outer, Inner can access private
members.
}
};
int x;
};
Conversely, the enclosing class is not treated as a friend of the nested class, and thus cannot
access its private members without explicitly being granted permission.
https://riptutorial.com/ 106
class Outer {
class Inner {
// friend class Outer;
int x;
};
Inner in;
public:
int get_x() {
return in.x; // Error: int Outer::Inner::x is private.
// Uncomment "friend" line above to fix.
}
};
Friends of a nested class are not automatically considered friends of the enclosing class; if they
need to be friends of the enclosing class as well, this must be declared separately. Conversely, as
the enclosing class is not automatically considered a friend of the nested class, neither will friends
of the enclosing class be considered friends of the nested class.
class Outer {
friend void barge_out(Outer& out, Inner& in);
class Inner {
friend void barge_in(Outer& out, Inner& in);
int i;
};
int o;
};
As with all other class members, nested classes can only be named from outside the class if they
have public access. However, you are allowed to access them regardless of access modifier, as
long as you don't explicitly name them.
class Outer {
struct Inner {
void func() { std::cout << "I have no private taboo.\n"; }
};
public:
static Inner make_Inner() { return Inner(); }
};
https://riptutorial.com/ 107
// ...
You can also create a type alias for a nested class. If a type alias is contained in the enclosing
class, the nested type and the type alias can have different access modifiers. If the type alias is
outside the enclosing class, it requires that either the nested class, or a typedef thereof, be public.
class Outer {
class Inner_ {};
public:
typedef Inner_ Inner;
};
// ...
As with other classes, nested classes can both derive from or be derived from by other classes.
struct Outer {
struct Inner : Base {};
};
This can be useful in situations where the enclosing class is derived from by another class, by
allowing the programmer to update the nested class as necessary. This can be combined with a
typedef to provide a consistent name for each enclosing class' nested class:
class BaseOuter {
struct BaseInner_ {
virtual void do_something() {}
virtual void do_something_else();
} b_in;
public:
typedef BaseInner_ Inner;
https://riptutorial.com/ 108
void BaseOuter::BaseInner_::do_something_else() {}
// ---
public:
typedef DerivedInner_ Inner;
void DerivedOuter::DerivedInner_::do_something_else() {}
// ...
// Calls BaseOuter::BaseInner_::do_something();
BaseOuter* b = new BaseOuter;
BaseOuter::Inner& bin = b->getInner();
bin.do_something();
b->getInner().do_something();
// Calls DerivedOuter::DerivedInner_::do_something();
BaseOuter* d = new DerivedOuter;
BaseOuter::Inner& din = d->getInner();
din.do_something();
d->getInner().do_something();
In the above case, both BaseOuter and DerivedOuter supply the member type Inner, as BaseInner_
and DerivedInner_, respectively. This allows nested types to be derived without breaking the
enclosing class' interface, and allows the nested type to be used polymorphically.
A class or struct can also define member type aliases, which are type aliases contained within,
and treated as members of, the class itself.
struct IHaveATypedef {
typedef int MyTypedef;
};
struct IHaveATemplateTypedef {
template<typename T>
using MyTemplateTypedef = std::vector<T>;
};
Like static members, these typedefs are accessed using the scope operator, ::.
IHaveATypedef::MyTypedef i = 5; // i is an int.
https://riptutorial.com/ 109
IHaveATemplateTypedef::MyTemplateTypedef<int> v; // v is a std::vector<int>.
As with normal type aliases, each member type alias is allowed to refer to any type defined or
aliased before, but not after, its definition. Likewise, a typedef outside the class definition can refer
to any accessible typedefs within the class definition, provided it comes after the class definition.
template<typename T>
struct Helper {
T get() const { return static_cast<T>(42); }
};
struct IHaveTypedefs {
// typedef MyTypedef NonLinearTypedef; // Error if uncommented.
typedef int MyTypedef;
typedef Helper<MyTypedef> MyTypedefHelper;
};
Member type aliases can be declared with any access level, and will respect the appropriate
access modifier.
class TypedefAccessLevels {
typedef int PrvInt;
protected:
typedef int ProInt;
public:
typedef int PubInt;
};
This can be used to provide a level of abstraction, allowing a class' designer to change its internal
workings without breaking code that relies on it.
class Something {
friend class SomeComplexType;
short s;
// ...
https://riptutorial.com/ 110
public:
typedef SomeComplexType MyHelper;
// ...
};
// ...
Something s;
Something::MyHelper hlp = s.get_helper();
In this situation, if the helper class is changed from SomeComplexType to some other type, only the
typedef and the friend declaration would need to be modified; as long as the helper class provides
the same functionality, any code that uses it as Something::MyHelper instead of specifying it by
name will usually still work without any modifications. In this manner, we minimise the amount of
code that needs to be modified when the underlying implementation is changed, such that the type
name only needs to be changed in one location.
class SomethingElse {
AnotherComplexType<bool, int, SomeThirdClass> helper;
public:
typedef decltype(helper) MyHelper;
private:
InternalVariable<MyHelper> ivh;
// ...
public:
MyHelper& get_helper() const { return helper; }
// ...
};
As with everything, however, this can be taken too far. If the typename is only used once or twice
internally and zero times externally, for example, there's no need to provide an alias for it. If it's
used hundreds or thousands of times throughout a project, or if it has a long enough name, then it
can be useful to provide it as a typedef instead of always using it in absolute terms. One must
balance forwards compatibility and convenience with the amount of unnecessary noise created.
This can also be used with template classes, to provide access to the template parameters from
outside the class.
template<typename T>
https://riptutorial.com/ 111
class SomeClass {
// ...
public:
typedef T MyParam;
MyParam getParam() { return static_cast<T>(42); }
};
template<typename T>
typename T::MyParam some_func(T& t) {
return t.getParam();
}
SomeClass<int> si;
int i = some_func(si);
This is commonly used with containers, which will usually provide their element type, and other
helper types, as member type aliases. Most of the containers in the C++ standard library, for
example, provide the following 12 helper types, along with any other special types they might
need.
template<typename T>
class SomeContainer {
// ...
public:
// Let's provide the same helper types as most standard containers.
typedef T value_type;
typedef std::allocator<value_type> allocator_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef MyIterator<value_type> iterator;
typedef MyConstIterator<value_type> const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
};
Prior to C++11, it was also commonly used to provide a "template typedef" of sorts, as the feature
wasn't yet available; these have become a bit less common with the introduction of alias
templates, but are still useful in some situations (and are combined with alias templates in other
situations, which can be very useful for obtaining individual components of a complex type such as
a function pointer). They commonly use the name type for their type alias.
template<typename T>
struct TemplateTypedef {
typedef T type;
}
TemplateTypedef<int>::type i; // i is an int.
This was often used with types with multiple template parameters, to provide an alias that defines
https://riptutorial.com/ 112
one or more of the parameters.
template<typename T>
struct MonoDisplayLine {
typedef Array<T, 80, 1> type;
};
A class is also allowed to have static members, which can be either variables or functions. These
are considered to be in the class' scope, but aren't treated as normal members; they have static
storage duration (they exist from the start of the program to the end), aren't tied to a particular
instance of the class, and only one copy exists for the entire class.
class Example {
static int num_instances; // Static data member (static member variable).
int i; // Non-static member variable.
public:
static std::string static_str; // Static data member (static member variable).
static int static_func(); // Static member function.
int Example::num_instances;
std::string Example::static_str = "Hello.";
// ...
https://riptutorial.com/ 113
// (&two.num_instances == &three.num_instances)
Static member variables are not considered to be defined inside the class, only declared, and thus
have their definition outside the class definition; the programmer is allowed, but not required, to
initialise static variables in their definition. When defining the member variables, the keyword
static is omitted.
class Example {
static int num_instances; // Declaration.
public:
static std::string static_str; // Declaration.
// ...
};
Due to this, static variables can be incomplete types (apart from void), as long as they're later
defined as a complete type.
struct ForwardDeclared;
class ExIncomplete {
static ForwardDeclared fd;
static ExIncomplete i_contain_myself;
static int an_array[];
};
ForwardDeclared ExIncomplete::fd;
ExIncomplete ExIncomplete::i_contain_myself;
int ExIncomplete::an_array[5];
Static member functions can be defined inside or outside the class definition, as with normal
member functions. As with static member variables, the keyword static is omitted when defining
static member functions outside the class definition.
public:
static int static_func() { return num_instances; }
// ...
// Or...
https://riptutorial.com/ 114
int Example::static_func() { return num_instances; }
void Example::set_str(const std::string& str) { static_str = str; }
If a static member variable is declared const but not volatile, and is of an integral or enumeration
type, it can be initialised at declaration, inside the class definition.
enum E { VAL = 5 };
struct ExConst {
const static int ci = 5; // Good.
static const E ce = VAL; // Good.
const static double cd = 5; // Error.
static const volatile int cvi = 5; // Error.
C++11
As of C++11, static member variables of LiteralType types (types that can be constructed at
compile time, according to constexpr rules) can also be declared as constexpr; if so, they must be
initialised within the class definition.
struct ExConstexpr {
constexpr static int ci = 5; // Good.
static constexpr double cd = 5; // Good.
constexpr static int carr[] = { 1, 1, 2 }; // Good.
static constexpr ConstexprConstructibleClass c{}; // Good.
constexpr static int bad_ci; // Error.
};
If a const or constexpr static member variable is odr-used (informally, if it has its address taken or
is assigned to a reference), then it must still have a separate definition, outside the class definition.
This definition is not allowed to contain an initialiser.
struct ExODR {
static const int odr_used = 5;
};
const int* odr_user = & ExODR::odr_used; // Error; uncomment above line to resolve.
As static members aren't tied to a given instance, they can be accessed using the scope operator,
::.
https://riptutorial.com/ 115
std::string str = Example::static_str;
They can also be accessed as if they were normal, non-static members. This is of historical
significance, but is used less commonly than the scope operator to prevent confusion over
whether a member is static or non-static.
Example ex;
std::string rts = ex.static_str;
Class members are able to access static members without qualifying their scope, as with non-
static class members.
class ExTwo {
static int num_instances;
int my_num;
public:
ExTwo() : my_num(num_instances++) {}
int ExTwo::num_instances;
They cannot be mutable, nor would they need to be; as they aren't tied to any given instance,
whether an instance is or isn't const doesn't affect static members.
struct ExDontNeedMutable {
int immuta;
mutable int muta;
static int i;
// ...
class ExAccess {
static int prv_int;
protected:
static int pro_int;
https://riptutorial.com/ 116
public:
static int pub_int;
};
int ExAccess::prv_int;
int ExAccess::pro_int;
int ExAccess::pub_int;
// ...
As they aren't tied to a given instance, static member functions have no this pointer; due to this,
they can't access non-static member variables unless passed an instance.
class ExInstanceRequired {
int i;
public:
ExInstanceRequired() : i(0) {}
Due to not having a this pointer, their addresses can't be stored in pointers-to-member-functions,
and are instead stored in normal pointers-to-functions.
struct ExPointer {
void nsfunc() {}
static void sfunc() {}
};
Due to not having a this pointer, they also cannot be const or volatile, nor can they have ref-
qualifiers. They also cannot be virtual.
struct ExCVQualifiersAndVirtual {
static void func() {} // Good.
static void cfunc() const {} // Error.
static void vfunc() volatile {} // Error.
static void cvfunc() const volatile {} // Error.
static void rfunc() & {} // Error.
static void rvfunc() && {} // Error.
https://riptutorial.com/ 117
};
As they aren't tied to a given instance, static member variables are effectively treated as special
global variables; they're created when the program starts, and destroyed when it exits, regardless
of whether any instances of the class actually exist. Only a single copy of each static member
variable exists (unless the variable is declared thread_local (C++11 or later), in which case there's
one copy per thread).
Static member variables have the same linkage as the class, whether the class has external or
internal linkage. Local classes and unnamed classes aren't allowed to have static members.
A class can have non-static member functions, which operate on individual instances of the class.
class CL {
public:
void member_function() {}
};
CL instance;
instance.member_function();
They can be defined either inside or outside the class definition; if defined outside, they are
specified as being in the class' scope.
struct ST {
void defined_inside() {}
void defined_outside();
};
void ST::defined_outside() {}
They can be CV-qualified and/or ref-qualified, affecting how they see the instance they're called
upon; the function will see the instance as having the specified cv-qualifier(s), if any. Which
version is called will be based on the instance's cv-qualifiers. If there is no version with the same
cv-qualifiers as the instance, then a more-cv-qualified version will be called if available.
struct CVQualifiers {
void func() {} // 1: Instance is non-cv-qualified.
void func() const {} // 2: Instance is const.
CVQualifiers non_cv_instance;
const CVQualifiers c_instance;
https://riptutorial.com/ 118
non_cv_instance.cv_only(); // Calls const volatile version.
c_instance.cv_only(); // Calls const volatile version.
C++11
Member function ref-qualifiers indicate whether or not the function is intended to be called on
rvalue instances, and use the same syntax as function cv-qualifiers.
struct RefQualifiers {
void func() & {} // 1: Called on normal instances.
void func() && {} // 2: Called on rvalue (temporary) instances.
};
RefQualifiers rf;
rf.func(); // Calls #1.
RefQualifiers{}.func(); // Calls #2.
struct BothCVAndRef {
void func() const& {} // Called on normal instances. Sees instance as const.
void func() && {} // Called on temporary instances.
};
They can also be virtual; this is fundamental to polymorphism, and allows a child class(es) to
provide the same interface as the parent class, while supplying their own functionality.
struct Base {
virtual void func() {}
};
struct Derived {
virtual void func() {}
};
Unnamed struct/class
void foo()
{
struct /* No name */ {
float x;
float y;
} point;
point.x = 42;
https://riptutorial.com/ 119
}
or
struct Circle
{
struct /* No name */ {
float x;
float y;
} center; // but a member name
float radius;
};
and later
Circle circle;
circle.center.x = 42.f;
struct InvalidCircle
{
struct /* No name */ {
float centerX;
float centerY;
}; // No member either.
float radius;
};
C++11
decltype(circle.point) otherPoint;
void print_square_coordinates()
{
const struct {float x; float y;} points[] = {
{-1, -1}, {-1, 1}, {1, -1}, {1, 1}
};
https://riptutorial.com/ 120
auto it = std::find(points, points + 4, topRightCorner);
std::cout << "top right corner is the "
<< 1 + std::distance(points, it) << "th\n";
}
https://riptutorial.com/ 121
Chapter 23: Client server examples
Examples
Hello TCP Server
Let me start by saying you should first visit Beej's Guide to Network Programming and give it a
quick read, which explains most of this stuff a bit more verbosely. We'll be creating a simple TCP
server here which will say "Hello World" to all incoming connections and then close them. Another
thing to note is, the server will be communicating to clients iteratively, which means one client at a
time. Make sure to check out relevant man pages as they might contain valuable information about
each function call and socket structures.
We'll run the server with a port, so we'll take an argument for port number as well. Let's get started
with code -
addrinfo hints, *res, *p; // we need 2 pointers, res to hold and p to iterate over
memset(&hints, 0, sizeof(hints));
// man getaddrinfo
int gAddRes = getaddrinfo(NULL, portNum, &hints, &res);
if (gAddRes != 0) {
std::cerr << gai_strerror(gAddRes) << "\n";
https://riptutorial.com/ 122
return -2;
}
// if no addresses found :(
if (!numOfAddr) {
std::cerr << "Found no host address to use\n";
return -3;
}
p = res;
https://riptutorial.com/ 123
// let's create a new socket, socketFD is returned as descriptor
// man socket for more information
// these calls usually return -1 as result of some error
int sockFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockFD == -1) {
std::cerr << "Error while creating socket\n";
freeaddrinfo(res);
return -4;
}
// if some error occurs, make sure to close socket and free resources
close(sockFD);
freeaddrinfo(res);
return -5;
}
// if some error occurs, make sure to close socket and free resources
close(sockFD);
freeaddrinfo(res);
return -6;
}
// send call sends the data you specify as second param and it's length as 3rd param,
also returns how many bytes were actually sent
auto bytes_sent = send(newFD, response.data(), response.length(), 0);
close(newFD);
https://riptutorial.com/ 124
}
close(sockFD);
freeaddrinfo(res);
return 0;
}
Detecting addresses
(1) IPv4 : 0.0.0.0
(2) IPv6 : ::
Enter the number of host address to bind with: 1
This program is complimentary to Hello TCP Server program, you can run either of them to check
the validity of each other. The program flow is quite common with Hello TCP server, so make sure
to take a look at that too.
#include <cstring>
#include <iostream>
#include <string>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
https://riptutorial.com/ 125
if (p == NULL) {
std::cerr << "No addresses found\n";
return -3;
}
return 0;
}
https://riptutorial.com/ 126
Chapter 24: Common compile/linker errors
(GCC)
Examples
error: '***' was not declared in this scope
Variables
Not compiling:
#include <iostream>
std::cout << i << std::endl; // i is not in the scope of the main function
return 0;
}
Fix:
#include <iostream>
return 0;
}
Functions
Most of the time this error occurs if the needed header is not included (e.g. using
std::cout without #include <iostream>)
Not compiling:
#include <iostream>
https://riptutorial.com/ 127
int main(int argc, char *argv[])
{
doCompile();
return 0;
}
void doCompile()
{
std::cout << "No!" << std::endl;
}
Fix:
#include <iostream>
return 0;
}
void doCompile()
{
std::cout << "No!" << std::endl;
}
Or:
#include <iostream>
return 0;
}
Note: The compiler interprets the code from top to bottom (simplification). Everything must be at
least declared (or defined) before usage.
This linker error happens, if the linker can't find a used symbol. Most of the time, this happens if a
used library is not linked against.
qmake:
https://riptutorial.com/ 128
LIBS += nameOfLib
cmake:
TARGET_LINK_LIBRARIES(target nameOfLib)
g++ call:
One might also forget to compile and link all used .cpp files (functionsModule.cpp defines the
needed function):
The compiler can't find a file (a source file uses #include "someFile.hpp").
qmake:
INCLUDEPATH += dir/Of/File
cmake:
include_directories(dir/Of/File)
g++ call:
https://riptutorial.com/ 129
Chapter 25: Compiling and Building
Introduction
Programs written in C++ need to be compiled before they can be run. There is a large variety of
compilers available depending on your operating system.
Remarks
Most operating systems ship without a compiler, and they have to be installed later. Some
common compilers choices are:
Please consult the appropriate compiler manual, on how to compile a C++ program.
Another option to use a specific compiler with its own specific build system, it is possible to let
generic build systems configure the project for a specific compiler or for the default installed one.
Examples
Compiling with GCC
Assuming a single source file named main.cpp, the command to compile and link an non-optimized
executable is as follows (Compiling without optimization is useful for initial development and
debugging, although -Og is officially recommended for newer GCC versions).
To produce an optimized executable for use in production, use one of the -O options (see: -O1, -O2,
-O3, -Os, -Ofast):
If the -O option is omitted, -O0, which means no optimizations, is used as default (specifying -O
without a number resolves to -O1).
Alternatively, use optimization flags from the O groups (or more experimental optimizations)
directly. The following example builds with -O2 optimization, plus one flag from the -O3 optimization
level:
https://riptutorial.com/ 130
To produce a platform-specific optimized executable (for use in production on the machine with
the same architecture), use:
Either of the above will produce a binary file that can be run with .\app.exe on Windows and ./app
on Linux, Mac OS, etc.
The -o flag can also be skipped. In this case, GCC will create default output executable a.exe on
Windows and a.out on Unix-like systems. To compile a file without linking it, use the -c option:
This produces an object file named file.o which can later be linked with other files to produce a
binary:
More about optimization options can be found at gcc.gnu.org. Of particular note are -Og
(optimization with an emphasis on debugging experience -- recommended for the standard edit-
compile-debug cycle) and -Ofast (all optimizations, including ones disregarding strict standards
compliance).
The -Wall flag enables warnings for many common errors and should always be used. To improve
code quality it is often encouraged also to use -Wextra and other warning flags which are not
automatically enabled by -Wall and -Wextra.
If the code expects a specific C++ standard, specify which standard to use by including the -std=
flag. Supported values correspond to the year of finalization for each version of the ISO C++
standard. As of GCC 6.1.0, valid values for the std= flag are c++98/c++03, c++11, c++14, and c++17/
c++1z. Values separated by a forward slash are equivalent.
GCC includes some compiler-specific extensions that are disabled when they conflict with a
standard specified by the -std= flag. To compile with all extensions enabled, the value gnu++XX may
be used, where XX is any of the years used by the c++ values listed above.
The default standard will be used if none is specified. For versions of GCC prior to 6.1.0, the
default is -std=gnu++03; in GCC 6.1.0 and greater, the default is -std=gnu++14.
Note that due to bugs in GCC, the -pthread flag must be present at compilation and linking for
GCC to support the C++ standard threading functionality introduced with C++11, such as
std::thread and std::wait_for. Omitting it when using threading functions may result in no
warnings but invalid results on some platforms.
https://riptutorial.com/ 131
Linking with libraries:
Use the -l option to pass the library name:
If the library is not in the standard library path, add the path with -L option:
If one library depends on another, put the dependent library before the independent library:
Or let the linker determine the ordering itself via --start-group and --end-group (note: this has
significant performance cost):
For programmers coming from GCC or Clang to Visual Studio, or programmers more comfortable
with the command line in general, you can use the Visual C++ compiler from the command line as
well as the IDE.
If you desire to compile your code from the command line in Visual Studio, you first need to set up
the command line environment. This can be done either by opening the Visual Studio Command
Prompt/Developer Command Prompt/x86 Native Tools Command Prompt/x64 Native Tools Command Prompt or
similar (as provided by your version of Visual Studio), or at the command prompt, by navigating to
the VC subdirectory of the compiler's install directory (typically \Program Files (x86)\Microsoft
Visual Studio x\VC, where x is the version number (such as 10.0 for 2010, or 14.0 for 2015) and
running the VCVARSALL batch file with a command-line parameter specified here.
Note that unlike GCC, Visual Studio doesn't provide a front-end for the linker (link.exe) via the
compiler (cl.exe), but instead provides the linker as a separate program, which the compiler calls
as it exits. cl.exe and link.exe can be used separately with different files and options, or cl can be
told to pass files and options to link if both tasks are done together. Any linking options specified
to cl will be translated into options for link, and any files not processed by cl will be passed
directly to link. As this is mainly a simple guide to compiling with the Visual Studio command line,
arguments for link will not be described at this time; if you need a list, see here.
https://riptutorial.com/ 132
Note that arguments to cl are case-sensitive, while arguments to link are not.
[Be advised that some of the following examples use the Windows shell "current directory"
variable, %cd%, when specifying absolute path names. For anyone unfamiliar with this variable, it
expands to the current working directory. From the command line, it will be the directory you were
in when you ran cl, and is specified in the command prompt by default (if your command prompt is
C:\src>, for example, then %cd% is C:\src\).]
Assuming a single source file named main.cpp in the current folder, the command to compile and
link an unoptimised executable (useful for initial development and debugging) is (use either of the
following):
cl main.cpp
// Generates object file "main.obj".
// Performs linking with "main.obj".
// Generates executable "main.exe".
cl /Od main.cpp
// Same as above.
// "/Od" is the "Optimisation: disabled" option, and is the default when no /O is specified.
Assuming an additional source file "niam.cpp" in the same directory, use the following:
cl main.cpp niam.cpp
// Generates object files "main.obj" and "niam.obj".
// Performs linking with "main.obj" and "niam.obj".
// Generates executable "main.exe".
cl main.cpp src\*.cpp
// Generates object file "main.obj", plus one object file for each ".cpp" file in folder
// "%cd%\src".
// Performs linking with "main.obj", and every additional object file generated.
// All object files will be in the current folder.
// Generates executable "main.exe".
cl /o name main.cpp
// Generates executable named "name.exe".
cl /o folder\ main.cpp
// Generates executable named "main.exe", in folder "%cd%\folder".
cl /o folder\name main.cpp
// Generates executable named "name.exe", in folder "%cd%\folder".
cl /Fename main.cpp
// Same as "/o name".
cl /Fefolder\ main.cpp
// Same as "/o folder\".
https://riptutorial.com/ 133
cl /Fefolder\name main.cpp
// Same as "/o folder\name".
Both /o and /Fe pass their parameter (let's call it o-param) to link as /OUT:o-param, appending the
appropriate extension (generally .exe or .dll) to "name" o-params as necessary. While both /o and
/Fe are to my knowledge identical in functionality, the latter is preferred for Visual Studio. /o is
marked as deprecated, and appears to mainly be provided for programmers more familiar with
GCC or Clang.
Note that while the space between /o and the specified folder and/or name is optional, there
cannot be a space between /Fe and the specified folder and/or name.
cl /O1 main.cpp
// Optimise for executable size. Produces small programs, at the possible expense of slower
// execution.
cl /O2 main.cpp
// Optimise for execution speed. Produces fast programs, at the possible expense of larger
// file size.
Finally, to produce a platform-specific optimized executable (for use in production on the machine
with the specified architecture), choose the appropriate command prompt or VCVARSALL parameter
for the target platform. link should detect the desired platform from the object files; if not, use the
/MACHINE option to explicitly specify the target platform.
// If compiling for x64, and LINK doesn't automatically detect target platform:
cl main.cpp /link /machine:X64
Any of the above will produce an executable with the name specified by /o or /Fe, or if neither is
provided, with a name identical to the first source or object file specified to the compiler.
https://riptutorial.com/ 134
cl /o yo zp.obj pz.cpp
// Generates "yo.exe".
cl /c main.cpp
// Generates object file "main.obj".
This tells cl to exit without calling link, and produces an object file, which can later be linked with
other files to produce a binary.
cl main.obj niam.cpp
// Generates object file "niam.obj".
// Performs linking with "main.obj" and "niam.obj".
// Generates executable "main.exe".
There are other valuable command line parameters as well, which it would be very useful for users
to know:
cl /EHsc main.cpp
// "/EHsc" specifies that only standard C++ ("synchronous") exceptions will be caught,
// and `extern "C"` functions will not throw exceptions.
// This is recommended when writing portable, platform-independent code.
cl /clr main.cpp
// "/clr" specifies that the code should be compiled to use the common language runtime,
// the .NET Framework's virtual machine.
// Enables the use of Microsoft's C++/CLI language in addition to standard ("native") C++,
// and creates an executable that requires .NET to run.
cl /Za main.cpp
// "/Za" specifies that Microsoft extensions should be disabled, and code should be
// compiled strictly according to ISO C++ specifications.
// This is recommended for guaranteeing portability.
cl /Zi main.cpp
// "/Zi" generates a program database (PDB) file for use when debugging a program, without
// affecting optimisation specifications, and passes the option "/DEBUG" to LINK.
cl /LD dll.cpp
// "/LD" tells CL to configure LINK to generate a DLL instead of an executable.
// LINK will output a DLL, in addition to an LIB and EXP file for use when linking.
// To use the DLL in other programs, pass its associated LIB to CL or LINK when compiling
those
// programs.
https://riptutorial.com/ 135
For anyone more familiar with *nix systems and/or GCC/Clang, cl, link, and other Visual Studio
command line tools can accept parameters specified with a hyphen (such as -c) instead of a slash
(such as /c). Additionally, Windows recognises either a slash or a backslash as a valid path
separator, so *nix-style paths can be used as well. This makes it easy to convert simple compiler
command lines from g++ or clang++ to cl, or vice versa, with minimal changes.
Of course, when porting command lines that use more complex g++ or clang++ options, you need to
look up equivalent commands in the applicable compiler documentations and/or on resource sites,
but this makes it easier to get things started with minimal time spent learning about new compilers.
In case you need specific language features for your code, a specific release of MSVC was
required. From Visual C++ 2015 Update 3 on it is possible to choose the version of the standard to
compile with via the /std flag. Possible values are /std:c++14 and /std:c++latest (/std:c++17 will
follow soon).
Note: In older versions of this compiler, specific feature flags were available however this was
mostly used for previews of new features.
4. Click Templates -> Visual C++ -> Win32 Console Application and then name the project
MyFirstProgram.
https://riptutorial.com/ 136
5. Click Ok
6. Click Next in the following window.
https://riptutorial.com/ 137
7. Check the Empty project box and then click Finish:
https://riptutorial.com/ 138
8. Right click on folder Source File then -> Add --> New Item :
https://riptutorial.com/ 139
9. Select C++ File and name the file main.cpp, then click Add:
https://riptutorial.com/ 140
10: Copy and paste the following code in the new file main.cpp:
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
return 0;
}
https://riptutorial.com/ 141
11. Click Debug -> Start Without Debugging (or press ctrl + F5) :
https://riptutorial.com/ 142
Compiling with Clang
As the Clang front-end is designed for being compatible with GCC, most programs that can be
compiled via GCC will compile when you swap g++ by clang++ in the build scripts. If no -std=version
is given, gnu11 will be used.
Windows users who are used to MSVC can swap cl.exe with clang-cl.exe. By default, clang tries
to be compatible with the highest version of MSVC that has been installed.
In the case of compiling with visual studio, clang-cl can be used by changing the Platform toolset
in the project properties.
In both cases, clang is only compatible via its front-end, though it also tries to generate binary
compatible object files. Users of clang-cl should note that the compatibility with MSVC is not
complete yet.
To use clang or clang-cl, one could use the default installation on certain Linux distributions or
those bundled with IDEs (like XCode on Mac). For other versions of this compiler or on platforms
which don't have this installed, this can be download from the official download page.
If you're using CMake to build your code you can usually switch the compiler by setting the CC and
CXX environment variables like this:
mkdir build
cd build
CC=clang CXX=clang++ cmake ..
cmake --build .
Online Compilers
https://riptutorial.com/ 143
Various websites provide online access to C++ compilers. Online compiler's feature set vary
significantly from site to site, but usually they allow to do the following:
Online compiler website behavior is usually quite restrictive as they allow anyone to run compilers
and execute arbitrary code on their server side, whereas ordinarily remote arbitrary code
execution is considered as vulnerability.
• Run a small code snippet from a machine which lacks C++ compiler (smartphones, tablets,
etc.).
• Ensure that code compiles successfully with different compilers and runs the same way
regardless the compiler it was compiled with.
• Learn or teach basics of C++.
• Learn modern C++ features (C++14 and C++17 in near future) when up-to-date C++
compiler is not available on local machine.
• Spot a bug in your compiler by comparison with a large set of other compilers. Check if a
compiler bug was fixed in future versions, which are unavailable on your machine.
• Solve online judge problems.
• Develop full-featured (even small) applications using C++. Usually online compilers do not
allow to link with third-party libraries or download build artifacts.
• Perform intensive computations. Sever-side computing resources are limited, so any user-
provided program will be killed after a few seconds of execution. The permitted execution
time is usually enough for testing and learning.
• Attack compiler server itself or any third-party hosts on the net.
Examples:
Disclaimer: documentation author(s) are not affiliated with any resources listed below.
Websites are listed alphabetically.
• http://codepad.org/ Online compiler with code sharing. Editing code after compiling with a
source code warning or error does not work so well.
• http://coliru.stacked-crooked.com/ Online compiler for which you specify the command line.
Provides both GCC and Clang compilers for use.
• http://cpp.sh/ - Online compiler with C++14 support. Does not allow you to edit compiler
command line, but some options are available via GUI controls.
• https://gcc.godbolt.org/ - Provides a wide list of compiler versions, architectures, and
disassembly output. Very useful when you need to inspect what your code compiles into by
different compilers. GCC, Clang, MSVC (CL), Intel compiler (icc), ELLCC, and Zapcc are
present, with one or more of these compilers available for the ARM, ARMv8 (as ARM64),
https://riptutorial.com/ 144
Atmel AVR, MIPS, MIPS64, MSP430, PowerPC, x86, and x64 architecutres. Compiler
command line arguments may be edited.
• https://ideone.com/ - Widely used on the Net to illustrate code snippet behavior. Provides
both GCC and Clang for use, but doesn't allow you to edit the compiler command line.
• http://melpon.org/wandbox - Supports numerous Clang and GNU/GCC compiler versions.
• http://onlinegdb.com/ - An extremely minimalistic IDE that includes an editor, a compiler
(gcc), and a debugger (gdb).
• http://rextester.com/ - Provides Clang, GCC, and Visual Studio compilers for both C and C++
(along with compilers for other languages), with the Boost library available for use.
• http://tutorialspoint.com/compile_cpp11_online.php - Full-featured UNIX shell with GCC, and
a user-friendly project explorer.
• http://webcompiler.cloudapp.net/ - Online Visual Studio 2015 compiler, provided by Microsoft
as part of RiSE4fun.
When you develop a C++ program, the next step is to compile the program before running it. The
compilation is the process which converts the program written in human readable language like C,
C++ etc into a machine code, directly understood by the Central Processing Unit. For example, if
you have a C++ source code file named prog.cpp and you execute the compile command,
There are 4 main stages involved in creating an executable file from the source file.
1. The C++ the preprocessor takes a C++ source code file and deals with the
headers(#include), macros(#define) and other preprocessor directives.
2. The expanded C++ source code file produced by the C++ preprocessor is compiled into the
assembly language for the platform.
3. The assembler code generated by the compiler is assembled into the object code for the
platform.
Preprocessing
The preprocessor handles the preprocessor directives, like #include and #define. It is agnostic of
the syntax of C++, which is why it must be used with care.
It works on one C++ source file at a time by replacing #include directives with the content of the
respective files (which is usually just declarations), doing replacement of macros (#define), and
selecting different portions of text depending of #if, #ifdef and #ifndef directives.
https://riptutorial.com/ 145
replacing tokens with other tokens (the operator ## enables merging two tokens when it make
sense).
After all this, the preprocessor produces a single output that is a stream of tokens resulting from
the transformations described above. It also adds some special markers that tell the compiler
where each line came from so that it can use those to produce sensible error messages.
Some errors can be produced at this stage with clever use of the #if and #error directives.
By using below compiler flag, we can stop the process at preprocessing stage.
g++ -E prog.cpp
Compilation
The compilation step is performed on each output of the preprocessor. The compiler parses the
pure C++ source code (now without any preprocessor directives) and converts it into assembly
code. Then invokes underlying back-end(assembler in toolchain) that assembles that code into
machine code producing actual binary file in some format(ELF, COFF, a.out, ...). This object file
contains the compiled code (in binary form) of the symbols defined in the input. Symbols in object
files are referred to by name.
Object files can refer to symbols that are not defined. This is the case when you use a declaration,
and don't provide a definition for it. The compiler doesn't mind this, and will happily produce the
object file as long as the source code is well-formed.
Compilers usually let you stop compilation at this point. This is very useful because with it you can
compile each source code file separately. The advantage this provides is that you don't need to
recompile everything if you only change a single file.
The produced object files can be put in special archives called static libraries, for easier reusing
later on.
It's at this stage that "regular" compiler errors, like syntax errors or failed overload resolution
errors, are reported.
In order to stop the process after the compile step, we can use the -S option:
Assembling
The assembler creates object code. On a UNIX system you may see files with a .o suffix (.OBJ on
MSDOS) to indicate object code files. In this phase the assembler converts those object files from
assembly code into machine level instructions and the file created is a relocatable object code.
Hence, the compilation phase generates the relocatable object program and this program can be
used in different places without having to compile again.
To stop the process after the assembly step, you can use the -c option:
https://riptutorial.com/ 146
g++ -Wall -ansi -c prog.cpp
Linking
The linker is what produces the final compilation output from the object files the assembler
produced. This output can be either a shared (or dynamic) library (and while the name is similar,
they don't have much in common with static libraries mentioned earlier) or an executable.
It links all the object files by replacing the references to undefined symbols with the correct
addresses. Each of these symbols can be defined in other object files or in libraries. If they are
defined in libraries other than the standard library, you need to tell the linker about them.
At this stage the most common errors are missing definitions or duplicate definitions. The former
means that either the definitions don't exist (i.e. they are not written), or that the object files or
libraries where they reside were not given to the linker. The latter is obvious: the same symbol was
defined in two different object files or libraries.
1. Download and install Code::Blocks here. If you're on Windows, be careful to select a file for
which the name contains mingw, the other files don't install any compiler.
https://riptutorial.com/ 147
https://riptutorial.com/ 148
3. Select "Console application" and click "Go":
4. Click "Next", select "C++", click "Next", select a name for your project and choose a folder to
save it in, click "Next" and then click "Finish".
5. Now you can edit and compile your code. A default code that prints "Hello world!" in the
console is already there. To compile and/or run your program, press one of the three
compile/run buttons in the toolbar:
https://riptutorial.com/ 149
https://riptutorial.com/ 150
To compile without running, press , to run without compiling again, press and to
compile and then run, press .
Compiling and running the default "Hello world!" code gives the following result:
https://riptutorial.com/ 151
building
https://riptutorial.com/ 152
Chapter 26: Concurrency With OpenMP
Introduction
This topic covers the basics of concurrency in C++ using OpenMP. OpenMP is documented in
more detail in the OpenMP tag.
Remarks
OpenMP does not require any special headers or libraries as it is a built-in compiler feature.
However, if you use any OpenMP API functions such as omp_get_thread_num(), you will need to
include omp.h and its library.
OpenMP pragma statements are ignored when the OpenMP option is not enabled during
compilation. You may want to refer to the compiler option in your compiler's manual.
Examples
OpenMP: Parallel Sections
As OpenMP is a built-in compiler feature, it works on any supported compilers without including
any libraries. You may wish to include omp.h if you want to use any of the openMP API features.
Sample Code
https://riptutorial.com/ 153
}
#pragma omp section
{
std::cout << "world " << std::endl;
/** Do something **/
}
}
// This line will not be executed until all the
// sections defined above terminates
std::cout << "end" << std::endl;
Outputs
This example produces 2 possible outputs and is dependent on the operating system and
hardware. The output also illustrates a race condition problem that would occur from such an
implementation.
OUTPUT A OUTPUT B
Output
https://riptutorial.com/ 154
• begin forever hello world end
As execution order is not guaranteed, you may observe any of the above output.
This example shows how to divide a loop into equal parts and execute them in parallel.
// Continue process
// Only when all threads completed their allocated
// loop job
...
*Please take extra care to not modify the size of the vector used in parallel for loops as allocated
range indices doesn't update automatically.
This example illustrates a concept to perform reduction or gathering using std::vector and
OpenMP.
Supposed we have a scenario where we want multiple threads to help us generate a bunch of
stuff, int is used here for simplicity and can be replaced with other data types.
This is particularly useful when you need to merge results from slaves to avoid segement faults or
memory access violations and do not wish to use libraries or custom sync container libraries.
// Tell the compiler to use all threads allocated for this parallel region
// to perform this loop in parts. Actual load appx = 1000000 / Thread Qty
https://riptutorial.com/ 155
// The nowait keyword tells the compiler that the slave threads don't
// have to wait for all other slaves to finish this for loop job
#pragma omp for nowait
for (size_t i = 0; i < 1000000; ++i
{
/* Do something */
....
Slave.push_back(...);
}
https://riptutorial.com/ 156
Chapter 27: Const Correctness
Syntax
• class ClassOne { public: bool non_modifying_member_function() const { /* ... */ } };
• int ClassTwo::non_modifying_member_function() const { /* ... */ }
• void ClassTwo::modifying_member_function() { /* ... */ }
• char non_param_modding_func(const ClassOne& one, const ClassTwo* two) { /* ... */ }
• float parameter_modifying_function(ClassTwo& one, ClassOne* two) { /* ... */ }
• short ClassThree::non_modding_non_param_modding_f(const ClassOne&) const { /* ... */ }
Remarks
const correctness is a very useful troubleshooting tool, as it allows the programmer to quickly
determine which functions might be inadvertently modifying code. It also prevents unintentional
errors, such as the one shown in Const Correct Function Parameters, from compiling properly and
going unnoticed.
It is much easier to design a class for const correctness, than it is to later add const correctness to
a pre-existing class. If possible, design any class that can be const correct so that it is const
correct, to save yourself and others the hassle of later modifying it.
Note that this can also be applied to volatile correctness if necessary, with the same rules as for
const correctness, but this is used much less often.
Refrences :
ISO_CPP
C++ Tutorial
Examples
The Basics
const correctness is the practice of designing code so that only code that needs to modify an
instance is able to modify an instance (i.e. has write access), and conversely, that any code that
doesn't need to modify an instance is unable to do so (i.e. only has read access). This prevents
the instance from being modified unintentionally, making code less errorprone, and documents
whether the code is intended to change the instance's state or not. It also allows instances to be
treated as const whenever they don't need to be modified, or defined as const if they don't need to
be changed after initialisation, without losing any functionality.
https://riptutorial.com/ 157
This is done by giving member functions const CV-qualifiers, and by making pointer/reference
parameters const, except in the case that they need write access.
class ConstCorrectClass {
int x;
public:
int getX() const { return x; } // Function is const: Doesn't modify instance.
void setX(int i) { x = i; } // Not const: Modifies instance.
};
// ...
Due to the nature of const correctness, this starts with the class' member functions, and works its
way outwards; if you try to call a non-const member function from a const instance, or from a non-
const instance being treated as const, the compiler will give you an error about it losing cv-
qualifiers.
In a const-correct class, all member functions which don't change logical state have this cv-
qualified as const, indicating that they don't modify the object (apart from any mutable fields, which
can freely be modified even in const instances); if a const cv-qualified function returns a reference,
that reference should also be const. This allows them to be called on both constant and non-cv-
qualified instances, as a const T* is capable of binding to either a T* or a const T*. This, in turn,
allows functions to declare their passed-by-reference parameters as const when they don't need to
be modified, without losing any functionality.
Furthermore, in a const correct class, all passed-by-reference function parameters will be const
correct, as discussed in Const Correct Function Parameters, so that they can only be modified when
the function explicitly needs to modify them.
https://riptutorial.com/ 158
// Assume class Field, with member function "void insert_value(int);".
class ConstIncorrect {
Field fld;
public:
ConstIncorrect(Field& f); // Modifies.
class ConstCorrectCVQ {
Field fld;
public:
ConstCorrectCVQ(Field& f); // Modifies.
const Field& getField() const; // Doesn't modify. Exposes member as const reference,
// preventing indirect modification.
void setField(Field& f); // Modifies.
ConstCorrectCVQ::ConstCorrectCVQ(Field& f) : fld(f) {}
Field& ConstCorrectCVQ::getField() const { return fld; }
void ConstCorrectCVQ::setField(Field& f) { fld = f; }
void ConstCorrectCVQ::doSomething(int i) {
fld.insert_value(i);
}
void ConstCorrectCVQ::doNothing() const {}
https://riptutorial.com/ 159
We can then combine this with Const Correct Function Parameters, causing the class to be fully
const-correct.
class ConstCorrect {
Field fld;
public:
ConstCorrect(const Field& f); // Modifies instance. Doesn't modify parameter.
const Field& getField() const; // Doesn't modify. Exposes member as const reference,
// preventing indirect modification.
void setField(const Field& f); // Modifies instance. Doesn't modify parameter.
This can also be combined with overloading based on constness, in the case that we want one
behaviour if the instance is const, and a different behaviour if it isn't; a common use for this is
constainers providing accessors that only allow modification if the container itself is non-const.
class ConstCorrectContainer {
int arr[5];
public:
// Subscript operator provides read access if instance is const, or read/write access
// otherwise.
int& operator[](size_t index) { return arr[index]; }
const int& operator[](size_t index) const { return arr[index]; }
// ...
};
This is commonly used in the standard library, with most containers providing overloads to take
constness into account.
In a const-correct function, all passed-by-reference parameters are marked as const unless the
function directly or indirectly modifies them, preventing the programmer from inadvertently
changing something they didn't mean to change. This allows the function to take both const and
non-cv-qualified instances, and in turn, causes the instance's this to be of type const T* when a
member function is called, where T is the class' type.
struct Example {
https://riptutorial.com/ 160
void func() { std::cout << 3 << std::endl; }
void func() const { std::cout << 5 << std::endl; }
};
int main() {
Example a, b;
const_incorrect_function(a, &b);
const_correct_function(a, &b);
}
// Output:
3
3
5
5
While the effects of this are less immediately visible than those of const correct class design (in
that const-correct functions and const-incorrect classes will cause compilation errors, while const-
correct classes and const-incorrect functions will compile properly), const correct functions will
catch a lot of errors that const incorrect functions would let slip through, such as the one below.
[Note, however, that a const-incorrect function will cause compilation errors if passed a const
instance when it expected a non-const one.]
if (vals.size() && (vals_ind != -1) && (vals_ind < vals.size()) && !(h.needs_recalc())) {
return vals[h.get_cache_index(v_ind)];
}
T temp = v[v_ind];
temp -= h.poll_device();
temp *= h.obtain_random();
temp += h.do_tedious_calculation(temp, v[h.get_last_handled_index()]);
https://riptutorial.com/ 161
v.push_back(temp); // Oops. Should've been accessing vals.
vals_ind = vals.size() - 1;
h.register_index(v_ind, vals_ind);
}
return vals[vals_ind];
}
return vals[vals_ind];
}
One of the more useful things about const correctness is that it serves as a way of documenting
code, providing certain guarantees to the programmer and other users. These guarantees are
enforced by the compiler due to constness, with a lack of constness in turn indicating that code
doesn't provide them.
This can be used to make assumptions about the state of the object after any given member
function is called, even without seeing the definition of that function:
// ConstMemberFunctions.h
class ConstMemberFunctions {
https://riptutorial.com/ 162
int val;
mutable int cache;
mutable bool state_changed;
public:
// Constructor clearly changes logical state. No assumptions necessary.
ConstMemberFunctions(int v = 0);
// We can assume this function doesn't change logical state, and doesn't call
// set_val(). It may or may not call squared_calc() or bad_func().
int calc() const;
// We can assume this function doesn't change logical state, and doesn't call
// set_val(). It may or may not call calc() or bad_func().
int squared_calc() const;
// We can assume this function doesn't change logical state, and doesn't call
// set_val(). It may or may not call calc() or squared_calc().
void bad_func() const;
// We can assume this function changes logical state, and may or may not call
// calc(), squared_calc(), or bad_func().
void set_val(int v);
};
Due to const rules, these assumptions will in fact be enforced by the compiler.
// ConstMemberFunctions.cpp
ConstMemberFunctions::ConstMemberFunctions(int v /* = 0*/)
: cache(0), val(v), state_changed(true) {}
return cache;
}
https://riptutorial.com/ 163
const Function Parameters:
• Any function with one or more parameters which are const can be assumed to have intent to
read those parameters, and:
○Shall not modify those parameters, or call any member functions that would modify
them.
○Shall not pass those parameters to any other function which would modify them and/or
call any member functions that would modify them.
• Conversely, any function with one or more parameters which aren't const can be assumed to
have intent to modify those parameters, and:
○May or may not modify those parameters, or call any member functions which whould
modify them.
○May or may not pass those parameters to other functions which would modify them
and/or call any member functions that would modify them.
This can be used to make assumptions about the state of the parameters after being passed to
any given function, even without seeing the definition of that function.
// function_parameter.h
// We can assume that c isn't modified (and c.set_val() isn't called), and isn't passed
// to non_qualified_function_parameter(). If passed to one_const_one_not(), it is the first
// parameter.
void const_function_parameter(const ConstMemberFunctions& c);
// We can assume that c is modified and/or c.set_val() is called, and may or may not be passed
// to any of these functions. If passed to one_const_one_not, it may be either parameter.
void non_qualified_function_parameter(ConstMemberFunctions& c);
// We can assume that c isn't modified (and c.set_val() isn't called), and isn't passed
// to non_qualified_function_parameter(). If passed to one_const_one_not(), it is the first
// parameter.
void bad_parameter(const ConstMemberFunctions& c);
Due to const rules, these assumptions will in fact be enforced by the compiler.
// function_parameter.cpp
https://riptutorial.com/ 164
c.set_val(42);
std::cout << "For the value 42, the output is: " << c.calc() << '\n'
<< "If squared, it's: " << c.squared_calc()
<< std::endl;
}
const_function_parameter(l);
const_function_parameter(r);
}
While it is possible to circumvent const correctness, and by extension break these guarantees, this
must be done intentionally by the programmer (just like breaking encapsulation with Machiavelli,
above), and is likely to cause undefined behaviour.
// ...
However, due to this requiring the programmer to very specifically tell the compiler that they intend
to ignore constness, and being inconsistent across compilers, it is generally safe to assume that
const correct code will refrain from doing so unless otherwise specified.
https://riptutorial.com/ 165
Read Const Correctness online: https://riptutorial.com/cplusplus/topic/7217/const-correctness
https://riptutorial.com/ 166
Chapter 28: const keyword
Syntax
• const Type myVariable = initial; // Declares a const variable; cannot be changed
• const Type &myReference = myVariable; // Declares a reference to a const variable
• const Type *myPointer = &myVariable; // Declares a pointer-to-const. The pointer can
change, but the underlying data member cannot be changed through the pointer
• Type * const myPointer = &myVariable; // Declares a const pointer. The pointer cannot be
reassigned to point to something else, but the underlying data member can be changed
• const Type * const myPointer = &myVariable; // Declares a const pointer-to-const.
Remarks
A variable marked as const cannot1 be changed. Attempting to call any non-const operations on it
will result in a compiler error.
1: Well, it can be changed through const_cast, but you should almost never use that
Examples
Const local variables
int f = 0;
e = &f; // OK; e is a non-const pointer-to-const,
// which means that it can be rebound to new int* or const int*
int *g = &f;
*g = 1; // OK; this value still can be changed through dereferencing
// a pointer-not-to-const
https://riptutorial.com/ 167
Const pointers
int a = 0, b = 2;
pA = &b;
*pB = b;
Member functions of a class can be declared const, which tells the compiler and future readers
that this function will not modify the object:
class MyClass
{
private:
int myInt_;
public:
int myInt() const { return myInt_; }
void setMyInt(int myInt) { myInt_ = myInt; }
};
In a const member function, the this pointer is effectively a const MyClass * instead of a MyClass *.
This means that you cannot change any member variables within the function; the compiler will
emit a warning. So setMyInt could not be declared const.
You should almost always mark member functions as const when possible. Only const member
functions can be called on a const MyClass.
static methods cannot be declared as const. This is because a static method belongs to a class
and is not called on object; therefore it can never modify object's internal variables. So declaring
static methods as const would be redundant.
In C++ methods that differs only by const qualifier can be overloaded. Sometimes there may be a
need of two versions of getter that return a reference to some member.
https://riptutorial.com/ 168
Let Foo be a class, that has two methods that perform identical operations and returns a reference
to an object of type Bar:
class Foo
{
public:
Bar& GetBar(/* some arguments */)
{
/* some calculations */
return bar;
}
// ...
};
The only difference between them is that one method is non-const and return a non-const
reference (that can be use to modify object) and the second is const and returns const reference.
To avoid the code duplication, there is a temptation to call one method from another. However, we
can not call non-const method from the const one. But we can call const method from non-const
one. That will require as to use 'const_cast' to remove the const qualifier.
struct Foo
{
Bar& GetBar(/*arguments*/)
{
return const_cast<Bar&>(const_cast<const Foo*>(this)->GetBar(/*arguments*/));
}
In code above, we call const version of GetBar from the non-const GetBar by casting this to const
type: const_cast<const Foo*>(this). Since we call const method from non-const, the object itself is
non-const, and casting away the const is allowed.
#include <iostream>
class Student
{
public:
https://riptutorial.com/ 169
char& GetScore(bool midterm)
{
return const_cast<char&>(const_cast<const Student*>(this)->GetScore(midterm));
}
private:
char midtermScore;
char finalScore;
};
int main()
{
// non-const object
Student a;
// We can assign to the reference. Non-const version of GetScore is called
a.GetScore(true) = 'B';
a.GetScore(false) = 'A';
// const object
const Student b(a);
// We still can call GetScore method of const object,
// because we have overloaded const version of GetScore
std::cout << b.GetScore(true) << b.GetScore(false) << '\n';
}
https://riptutorial.com/ 170
Chapter 29: Constant class member
functions
Remarks
What does 'const member functions' of a class really means. The simple definition seems to be
that, a const member function cannot change the object. But what does 'can not change' really
means here. It simply means that you cannot do an assignment for class data members.
However, you can do other indirect operations like inserting an entry into a map as shown in the
example. Allowing this might look like this const function is modifying the object (yes, it does in
one sense), but it is allowed.
So, the real meaning is that a const member function cannot do an assignment for the class data
variables. But it can do other stuff like explained in the example.
Examples
constant member function
#include <iostream>
#include <map>
#include <string>
class A {
public:
map<string, string> * mapOfStrings;
public:
A() {
mapOfStrings = new map<string, string>();
}
void insertEntry(string const & key, string const & value) const {
(*mapOfStrings)[key] = value; // This works? Yes it does.
delete mapOfStrings; // This also works
mapOfStrings = new map<string, string>(); // This * does * not work
}
void refresh() {
delete mapOfStrings;
mapOfStrings = new map<string, string>(); // Works as refresh is non const function
}
https://riptutorial.com/ 171
A var;
var.insertEntry("abc", "abcValue");
var.getEntry("abc");
getchar();
return 0;
}
https://riptutorial.com/ 172
Chapter 30: constexpr
Introduction
constexpr is a keyword that can be used to mark a variable's value as a constant expression, a
function as potentially usable in constant expressions, or (since C++17) an if statement as having
only one of its branches selected to be compiled.
Remarks
The constexpr keyword was added in C++11 but for a few years since the C++11 standard was
published, not all major compilers supported it. at the time that the C++11 standard was published.
As of the time of publication of C++14, all major compilers support constexpr.
Examples
constexpr variables
A variable declared constexpr is implicitly const and its value may be used as a constant
expression.
A constexpr is type-safe replacement for #define based compile-time expressions. With constexpr
the compile-time evaluated expression is replaced with the result. For example:
C++11
int main()
{
constexpr int N = 10 + 2;
cout << N;
}
#define N 10 + 2
int main()
{
cout << N;
}
https://riptutorial.com/ 173
will produce:
cout << 10 + 2;
which will obviously be converted to cout << 10 + 2;. However, the compiler would have to do
more work. Also, it creates a problem if not used correctly.
cout << N * 2;
forms:
cout << 10 + 2 * 2; // 14
A const variable is a variable which needs memory for its storage. A constexpr does not. A
constexpr produces compile time constant, which cannot be changed. You may argue that const
may also not be changed. But consider:
int main()
{
const int size1 = 10;
const int size2 = abs(10);
int arr_one[size1];
int arr_two[size2];
}
With most compilers the second statement will fail (may work with GCC, for example). The size of
any array, as you might know, has to be a constant expression (i.e. results in compile-time value).
The second variable size2 is assigned some value that is decided at runtime (even though you
know it is 10, for the compiler it is not compile-time).
This means that a const may or may not be a true compile-time constant. You cannot guarantee or
enforce that a particular const value is absolutely compile-time. You may use #define but it has its
own pitfalls.
C++11
int main()
{
constexpr int size = 10;
int arr[size];
}
https://riptutorial.com/ 174
A constexpr expression must evaluate to a compile-time value. Thus, you cannot use:
C++11
C++11
C++11
constexpr functions
A function that is declared constexpr is implicitly inline and calls to such a function potentially yield
constant expressions. For example, the following function, if called with constant expression
arguments, yields a constant expression too:
C++11
Thus, the result of the function call may be used as an array bound or a template argument, or to
initialize a constexpr variable:
C++11
int main()
{
constexpr int S = Sum(10,20);
int Array[S];
int Array2[Sum(20,30)]; // 50 array size, compile time
}
Note that if you remove constexpr from function's return type specification, assignment to S will not
work, as S is a constexpr variable, and must be assigned a compile-time const. Similarly, size of
https://riptutorial.com/ 175
array will also not be a constant-expression, if function Sum is not constexpr.
Interesting thing about constexpr functions is that you may also use it like ordinary functions:
C++11
int a = 20;
auto sum = Sum(a, abs(-20));
Sumwill not be a constexpr function now, it will be compiled as an ordinary function, taking variable
(non-constant) arguments, and returning non-constant value. You need not to write two functions.
It also means that if you try to assign such call to a non-const variable, it won't compile:
C++11
int a = 20;
constexpr auto sum = Sum(a, abs(-20));
The reason is simple: constexpr must only be assigned a compile-time constant. However, the
above function call makes Sum a non-constexpr (R-value is non-const, but L-value is declaring itself
to be constexpr).
The constexpr function must also return a compile-time constant. Following will not compile:
C++11
Because a1 is a non-constexpr variable, and prohibits the function from being a true constexpr
function. Making it constexpr and assigning it a will also not work - since value of a (incoming
parameter) is still not yet known:
C++11
C++11
https://riptutorial.com/ 176
}
Since abs(a) is not a constant expression (even abs(10) will not work, since abs is not returning a
constexpr int !
C++11
We crafted our own Abs function which is a constexpr, and the body of Abs also doesn't break any
rule. Also, at the call site (inside Sum), the expression evaluates to a constexpr. Hence, the call to
Sum(-10, 20) will be a compile-time constant expression resulting to 30.
Static if statement
C++17
The if constexpr statement can be used to conditionally compile code. The condition must be a
constant expression. The branch not selected is discarded. A discarded statement inside a
template is not instantiated. For example:
In addition, variables and functions that are odr-used only inside discarded statements are not
required to be defined, and discarded return statements are not used for function return type
deduction.
if constexpr is distinct from #ifdef. #ifdef conditionally compiles code, but only based on
conditions that can be evaluated at preprocessing time. For example, #ifdef could not be used to
conditionally compile code depending on the value of a template parameter. On the other hand, if
constexpr cannot be used to discard syntactically invalid code, while #ifdef can.
if constexpr(false) {
foobar; // error; foobar has not been declared
std::vector<int> v("hello, world"); // error; no matching constructor
}
https://riptutorial.com/ 177
Read constexpr online: https://riptutorial.com/cplusplus/topic/3899/constexpr
https://riptutorial.com/ 178
Chapter 31: Copy Elision
Examples
Purpose of copy elision
There are places in the standard where an object is copied or moved in order to initialize an
object. Copy elision (sometimes called return value optimization) is an optimization whereby,
under certain specific circumstances, a compiler is permitted to avoid the copy or move even
though the standard says that it must happen.
std::string get_string()
{
return std::string("I am a string.");
}
According to the strict wording of the standard, this function will initialize a temporary std::string,
then copy/move that into the return value object, then destroy the temporary. The standard is very
clear that this is how the code is interpreted.
Copy elision is a rule that permits a C++ compiler to ignore the creation of the temporary and its
subsequent copy/destruction. That is, the compiler can take the initializing expression for the
temporary and initialize the function's return value from it directly. This obviously saves
performance.
1. The type must have the copy/move constructor that would have been called. Even if the
compiler elides the copy/move, the type must still be able to have been copied/moved.
C++11
struct my_type
{
my_type() = default;
my_type(const my_type &) {std::cout <<"Copying\n";}
my_type(my_type &&) {std::cout <<"Moving\n";}
};
my_type func()
{
return my_type();
}
https://riptutorial.com/ 179
What will calling func do? Well, it will never print "Copying", since the temporary is an rvalue and
my_type is a moveable type. So will it print "Moving"?
Without the copy elision rule, this would be required to always print "Moving". But because the
copy elision rule exists, the move constructor may or may not be called; it is implementation-
dependent.
And therefore, you cannot depend on the calling of copy/move constructors in contexts where
elision is possible.
Because elision is an optimization, your compiler may not support elision in all cases. And
regardless of whether the compiler elides a particular case or not, the type must still support the
operation being elided. So if a copy construction is elided, the type must still have a copy
constructor, even though it will not be called.
C++17
Normally, elision is an optimization. While virtually every compiler support copy elision in the
simplest of cases, having elision still places a particular burden on users. Namely, the type who's
copy/move is being elided must still have the copy/move operation that was elided.
For example:
std::mutex a_mutex;
std::lock_guard<std::mutex> get_lock()
{
return std::lock_guard<std::mutex>(a_mutex);
}
This might be useful in cases where a_mutex is a mutex that is privately held by some system, yet
an external user might want to have a scoped lock to it.
This is also not legal, because std::lock_guard cannot be copied or moved. Even though virtually
every C++ compiler will elide the copy/move, the standard still requires the type to have that
operation available.
Until C++17.
C++17 mandates elision by effectively redefining the very meaning of certain expressions so that
no copy/moving takes place. Consider the above code.
Under pre-C++17 wording, that code says to create a temporary and then use the temporary to
copy/move into the return value, but the temporary copy can be elided. Under C++17 wording, that
does not create a temporary at all.
In C++17, any prvalue expression, when used to initialize an object of the same type as the
expression, does not generate a temporary. The expression directly initializes that object. If you
return a prvalue of the same type as the return value, then the type need not have a copy/move
https://riptutorial.com/ 180
constructor. And therefore, under C++17 rules, the above code can work.
The C++17 wording works in cases where the prvalue's type matches the type being initialized. So
given get_lock above, this will also not require a copy/move:
Since the result of get_lock is a prvalue expression being used to initialize an object of the same
type, no copying or moving will happen. That expression never creates a temporary; it is used to
directly initialize the_lock. There is no elision because there is no copy/move to be elided elide.
The term "guaranteed copy elision" is therefore something of a misnomer, but that is the name of
the feature as it is proposed for C++17 standardization. It does not guarantee elision at all; it
eliminates the copy/move altogether, redefining C++ so that there never was a copy/move to be
elided.
This feature only works in cases involving a prvalue expression. As such, this uses the usual
elision rules:
std::mutex a_mutex;
std::lock_guard<std::mutex> get_lock()
{
std::lock_guard<std::mutex> my_lock(a_mutex);
//Do stuff
return my_lock;
}
While this is a valid case for copy elision, C++17 rules do not eliminate the copy/move in this case.
As such, the type must still have a copy/move constructor to use to initialize the return value. And
since lock_guard does not, this is still a compile error. Implementations are allowed to refuse to
elide copies when passing or returning an object of trivially-copyable type. This is to allow moving
such objects around in registers, which some ABIs might mandate in their calling conventions.
struct trivially_copyable {
int a;
};
If you return a prvalue expression from a function, and the prvalue expression has the same type
as the function's return type, then the copy from the prvalue temporary can be elided:
std::string func()
{
return std::string("foo");
}
https://riptutorial.com/ 181
Pretty much all compilers will elide the temporary construction in this case.
Parameter elision
When you pass an argument to a function, and the argument is a prvalue expression of the
function's parameter type, and this type is not a reference, then the prvalue's construction can be
elided.
func(std::string("foo"));
This says to create a temporary string, then move it into the function parameter str. Copy elision
permits this expression to directly create the object in str, rather than using a temporary+move.
This is a useful optimization for cases where a constructor is declared explicit. For example, we
could have written the above as func("foo"), but only because string has an implicit constructor
that converts from a const char* to a string. If that constructor was explicit, we would be forced to
use a temporary to call the explicit constructor. Copy elision saves us from having to do a
needless copy/move.
• represents an automatic variable local to that function, which will be destroyed after the
return
• the automatic variable is not a function parameter
• and the type of the variable is the same type as the function's return type
If all of these are the case, then the copy/move from the lvalue can be elided:
std::string func()
{
std::string str("foo");
//Do stuff
return str;
}
More complex cases are eligible for elision, but the more complex the case, the less likely the
compiler will be to actually elide it:
std::string func()
{
std::string ret("foo");
if(some_condition)
{
return "bar";
}
return ret;
}
https://riptutorial.com/ 182
The compiler could still elide ret, but the chances of them doing so go down.
If you use a prvalue expression to copy initialize a variable, and that variable has the same type as
the prvalue expression, then the copying can be elided.
Copy initialization effectively transforms this into std::string str("foo"); (there are minor
differences).
std::string func()
{
return std::string("foo");
}
Without copy elision, this would provoke 2 calls to std::string's move constructor. Copy elision
permits this to call the move constructor 1 or zero times, and most compilers will opt for the latter.
https://riptutorial.com/ 183
Chapter 32: Copying vs Assignment
Syntax
• Copy Constructor
• MyClass( const MyClass& other );
• MyClass( MyClass& other );
• MyClass( volatile const MyClass& other );
• MyClass( volatile MyClass& other );
• Assignment Constructor
• MyClass& operator=( const MyClass& rhs );
• MyClass& operator=( MyClass& rhs );
• MyClass& operator=( MyClass rhs );
• const MyClass& operator=( const MyClass& rhs );
• const MyClass& operator=( MyClass& rhs );
• const MyClass& operator=( MyClass rhs );
• MyClass operator=( const MyClass& rhs );
• MyClass operator=( MyClass& rhs );
• MyClass operator=( MyClass rhs );
Parameters
Right Hand Side of the equality for both copy and assignment
rhs constructors. For example the assignment constructor : MyClass
operator=( MyClass& rhs );
Placeholder Placeholder
Remarks
Other Good Resources for further research :
GeeksForGeeks
C++ Articles
Examples
Assignment Operator
https://riptutorial.com/ 184
The Assignment Operator is when you replace the data with an already existing(previously
initialized) object with some other object's data. Lets take this as an example:
// Assignment Operator
#include <iostream>
#include <string>
using std::cout;
using std::endl;
class Foo
{
public:
Foo(int data)
{
this->data = data;
}
~Foo(){};
Foo& operator=(const Foo& rhs)
{
data = rhs.data;
return *this;
}
int data;
};
int main()
{
Foo foo(2); //Foo(int data) called
Foo foo2(42);
foo = foo2; // Assignment Operator Called
cout << foo.data << endl; //Prints 42
}
You can see here I call the assignment operator when I already initialized the foo object. Then
later I assign foo2 to foo . All the changes to appear when you call that equal sign operator is
defined in your operator= function. You can see a runnable output here: http://cpp.sh/3qtbm
Copy Constructor
Copy constructor on the other hand , is the complete opposite of the Assignment Constructor. This
time, it is used to initialize an already nonexistent(or non-previously initialized) object. This means
it copies all the data from the object you are assigning it to , without actually initializing the object
that is being copied onto. Now Let's take a look at the same code as before but modify the
assignment constructor to be a copy constructor :
// Copy Constructor
#include <iostream>
#include <string>
using std::cout;
using std::endl;
class Foo
{
https://riptutorial.com/ 185
public:
Foo(int data)
{
this->data = data;
}
~Foo(){};
Foo(const Foo& rhs)
{
data = rhs.data;
}
int data;
};
int main()
{
Foo foo(2); //Foo(int data) called
Foo foo2 = foo; // Copy Constructor called
cout << foo2.data << endl;
}
You can see here Foo foo2 = foo; in the main function I immediately assign the object before
actually initializing it, which as said before means it's a copy constructor. And notice that I didn't
need to pass the parameter int for the foo2 object since I automatically pulled the previous data
from the object foo. Here is an example output : http://cpp.sh/5iu7
Ok we have briefly looked over what the copy constructor and assignment constructor are above
and gave examples of each now let's see both of them in the same code. This code will be similar
as above two. Let's take this :
using std::cout;
using std::endl;
class Foo
{
public:
Foo(int data)
{
this->data = data;
}
~Foo(){};
Foo(const Foo& rhs)
{
data = rhs.data;
}
https://riptutorial.com/ 186
int data;
};
int main()
{
Foo foo(2); //Foo(int data) / Normal Constructor called
Foo foo2 = foo; //Copy Constructor Called
cout << foo2.data << endl;
Foo foo3(42);
foo3=foo; //Assignment Constructor Called
cout << foo3.data << endl;
}
Output:
2
2
Here you can see we first call the copy constructor by executing the line Foo foo2 = foo; . Since
we didn't initialize it previously. And then next we call the assignment operator on foo3 since it was
already initialized foo3=foo;
https://riptutorial.com/ 187
Chapter 33: Curiously Recurring Template
Pattern (CRTP)
Introduction
A pattern in which a class inherits from a class template with itself as one of its template
parameters. CRTP is usually used to provide static polymorphism in C++.
Examples
The Curiously Recurring Template Pattern (CRTP)
CRTP is a powerful, static alternative to virtual functions and traditional inheritance that can be
used to give types properties at compile time. It works by having a base class template which
takes, as one of its template parameters, the derived class. This permits it to legally perform a
static_cast of its this pointer to the derived class.
Of course, this also means that a CRTP class must always be used as the base class of some
other class. And the derived class must pass itself to the base class.
C++14
Let's say you have a set of containers that all support the functions begin() and end(). The
standard library's requirements for containers require more functionality. We can design a CRTP
base class that provides that functionality, based solely on begin() and end():
#include <iterator>
template <typename Sub>
class Container {
private:
// self() yields a reference to the derived type
Sub& self() { return *static_cast<Sub*>(this); }
Sub const& self() const { return *static_cast<Sub const*>(this); }
public:
decltype(auto) front() {
return *self().begin();
}
decltype(auto) back() {
return *std::prev(self().end());
}
decltype(auto) operator[](std::size_t i) {
return *std::next(self().begin(), i);
https://riptutorial.com/ 188
}
};
The above class provides the functions front(), back(), size(), and operator[] for any subclass
which provides begin() and end(). An example subclass is a simple dynamically allocated array:
#include <memory>
// A dynamically allocated array
template <typename T>
class DynArray : public Container<DynArray<T>> {
public:
using Base = Container<DynArray<T>>;
DynArray(std::size_t size)
: size_{size},
data_{std::make_unique<T[]>(size_)}
{ }
private:
std::size_t size_;
std::unique_ptr<T[]> data_;
};
Users of the DynArray class can use the interfaces provided by the CRTP base class easily as
follows:
DynArray<int> arr(10);
arr.front() = 2;
arr[2] = 5;
assert(arr.size() == 10);
Usefulness: This pattern particularly avoids virtual function calls at run-time which occur to
traverse down the inheritance hierarchy and simply relies on static casts:
DynArray<int> arr(10);
DynArray<int>::Base & base = arr;
base.begin(); // no virtual calls
The only static cast inside the function begin() in the base class Container<DynArray<int>> allows
the compiler to drastically optimize the code and no virtual table look up happens at runtime.
Limitations: Because the base class is templated and different for two different DynArrays it is not
possible to store pointers to their base classes in an type-homogenous array as one could
generally do with normal inheritance where the base class is not dependent on the derived type:
class A {};
class B: public A{};
A* a = new B;
https://riptutorial.com/ 189
CRTP to avoid code duplication
struct IShape
{
virtual ~IShape() = default;
Each child type of IShape needs to implement the same function the same way. That's a lot of extra
typing. Instead, we can introduce a new type in the hierarchy that does this for us:
And now, each shape simply needs to inherit from the acceptor:
https://riptutorial.com/ 190
Read Curiously Recurring Template Pattern (CRTP) online:
https://riptutorial.com/cplusplus/topic/9269/curiously-recurring-template-pattern--crtp-
https://riptutorial.com/ 191
Chapter 34: Data Structures in C++
Examples
Linked List implementation in C++
class listNode
{
public:
int data;
listNode *next;
listNode(int val):data(val),next(NULL){}
};
class List
{
public:
listNode *head;
List():head(NULL){}
void insertAtBegin(int val);
void insertAtEnd(int val);
void insertAtPos(int val);
void remove(int val);
void print();
~List();
};
https://riptutorial.com/ 192
{
ptr=ptr->next;
}
ptr->next=newnode;
}
https://riptutorial.com/ 193
{
listNode *ptr=this->head;
while(ptr!=NULL)
{
cout<<ptr->data<<" " ;
ptr=ptr->next;
}
cout<<endl;
}
List::~List()
{
listNode *ptr=this->head,*next=NULL;
while(ptr!=NULL)
{
next=ptr->next;
delete(ptr);
ptr=next;
}
}
https://riptutorial.com/ 194
Chapter 35: Date and time using header
Examples
Measuring time using
The system_clock can be used to measure the time elapsed during some part of a program's
execution.
c++11
#include <iostream>
#include <chrono>
#include <thread>
int main() {
auto start = std::chrono::system_clock::now(); // This and "end"'s type is
std::chrono::time_point
{ // The code to test
std::this_thread::sleep_for(std::chrono::seconds(2));
}
auto end = std::chrono::system_clock::now();
In this example, sleep_for was used to make the active thread sleep for a time period measured in
std::chrono::seconds, but the code between braces could be any function call that takes some time
to execute.
This example shows how to find number of days between two dates. A date is specified by
year/month/day of month, and additionally hour/minute/second.
#include <iostream>
#include <string>
#include <chrono>
#include <ctime>
/***
* Creates a std::tm structure from raw date.
*
* \param year (must be 1900 or greater)
* \param month months since January – [1, 12]
* \param day day of the month – [1, 31]
* \param minutes minutes after the hour – [0, 59]
* \param seconds seconds after the minute – [0, 61](until C++11) / [0, 60] (since C++11)
*
https://riptutorial.com/ 195
* Based on http://en.cppreference.com/w/cpp/chrono/c/tm
*/
std::tm CreateTmStruct(int year, int month, int day, int hour, int minutes, int seconds) {
struct tm tm_ret = {0};
tm_ret.tm_sec = seconds;
tm_ret.tm_min = minutes;
tm_ret.tm_hour = hour;
tm_ret.tm_mday = day;
tm_ret.tm_mon = month - 1;
tm_ret.tm_year = year - 1900;
return tm_ret;
}
return diff_in_days.count();
}
int main()
{
for ( int year = 2000; year <= 2016; ++year )
std::cout << "There are " << get_days_in_year(year) << " days in " << year << "\n";
}
https://riptutorial.com/ 196
Chapter 36: decltype
Introduction
The keyword decltype can be used to get the type of a variable, function or an expression.
Examples
Basic Example
int a = 10;
float a=99.0f;
Another example
std::vector<int> intVector;
And we want to declare an iterator for this vector. An obvious idea is to use auto. However, it may
be needed just declare an iterator variable (and not to assign it to anything). We would do:
vector<int>::iterator iter;
However, with decltype it becomes easy and less error prone (if type of intVector changes).
decltype(intVector)::iterator iter;
Alternatively:
decltype(intVector.begin()) iter;
In second example, the return type of begin is used to determine the actual type, which is
https://riptutorial.com/ 197
vector<int>::iterator.
https://riptutorial.com/ 198
Chapter 37: Design pattern implementation in
C++
Introduction
On this page, you can find examples of how design patterns are implemented in C++. For the
details on these patterns, you can check out the design patterns documentation.
Remarks
A design pattern is a general reusable solution to a commonly occurring problem within a given
context in software design.
Examples
Observer pattern
Observer Pattern's intent is to define a one-to-many dependency between objects so that when
one object changes state, all its dependents are notified and updated automatically.
The subject and observers define the one-to-many relationship. The observers are dependent on
the subject such that when the subject's state changes, the observers get notified. Depending on
the notification, the observers may also be updated with new values.
#include <iostream>
#include <vector>
class Subject;
class Observer
{
public:
virtual ~Observer() = default;
virtual void Update(Subject&) = 0;
};
class Subject
{
public:
virtual ~Subject() = default;
void Attach(Observer& o) { observers.push_back(&o); }
void Detach(Observer& o)
{
observers.erase(std::remove(observers.begin(), observers.end(), &o));
}
void Notify()
{
https://riptutorial.com/ 199
for (auto* o : observers) {
o->Update(*this);
}
}
private:
std::vector<Observer*> observers;
};
Notify();
}
private:
int hour;
int minute;
int second;
};
void Draw()
{
int hour = subject.GetHour();
int minute = subject.GetMinute();
int second = subject.GetSecond();
private:
ClockTimer& subject;
};
https://riptutorial.com/ 200
explicit AnalogClock(ClockTimer& s) : subject(s) { subject.Attach(*this); }
~AnalogClock() { subject.Detach(*this); }
void Update(Subject& theChangedSubject) override
{
if (&theChangedSubject == &subject) {
Draw();
}
}
void Draw()
{
int hour = subject.GetHour();
int minute = subject.GetMinute();
int second = subject.GetSecond();
int main()
{
ClockTimer timer;
DigitalClock digitalClock(timer);
AnalogClock analogClock(timer);
Output:
1. Objects (DigitalClock or AnalogClock object) use the Subject interfaces (Attach() or Detach())
either to subscribe (register) as observers or unsubscribe (remove) themselves from being
observers (subject.Attach(*this); , subject.Detach(*this);.
3. All observers need to implement the Observer interface. This interface just has one method,
Update(), that gets called when the Subject's state changes (Update(Subject &))
4. In addition to the Attach() and Detach() methods, the concrete subject implements a Notify()
method that is used to update all the current observers whenever state changes. But in this
case, all of them are done in the parent class, Subject (Subject::Attach (Observer&), void
Subject::Detach(Observer&) and void Subject::Notify() .
5. The Concrete object may also have methods for setting and getting its state.
https://riptutorial.com/ 201
6. Concrete observers can be any class that implements the Observer interface. Each observer
subscribe (register) with a concrete subject to receive update (subject.Attach(*this); ).
7. The two objects of Observer Pattern are loosely coupled, they can interact but with little
knowledge of each other.
Variation:
Signals and slots is a language construct introduced in Qt, which makes it easy to implement the
Observer pattern while avoiding boilerplate code. The concept is that controls (also known as
widgets) can send signals containing event information which can be received by other controls
using special functions known as slots. The slot in Qt must be a class member declared as such.
The signal/slot system fits well with the way Graphical User Interfaces are designed. Similarly, the
signal/slot system can be used for asynchronous I/O (including sockets, pipes, serial devices, etc.)
event notification or to associate timeout events with appropriate object instances and methods or
functions. No registration/deregistration/invocation code need be written, because Qt's Meta
Object Compiler (MOC) automatically generates the needed infrastructure.
The C# language also supports a similar construct although with a different terminology and
syntax: events play the role of signals, and delegates are the slots. Additionally, a delegate can be
a local variable, much like a function pointer, while a slot in Qt must be a class member declared
as such.
Adapter Pattern
Convert the interface of a class into another interface clients expect. Adapter (or Wrapper) lets
classes work together that couldn't otherwise because of incompatible interfaces. Adapter
pattern's motivation is that we can reuse existing software if we can modify the interface.
4. In STL, stack adapted from vector: When stack executes push(), underlying vector does
vector::push_back().
Example:
#include <iostream>
https://riptutorial.com/ 202
// Legacy component (Adaptee)
class LegacyRectangle
{
public:
LegacyRectangle(int x1, int y1, int x2, int y2) {
x1_ = x1;
y1_ = y1;
x2_ = x2;
y2_ = y2;
std::cout << "LegacyRectangle(x1,y1,x2,y2)\n";
}
void oldDraw() {
std::cout << "LegacyRectangle: oldDraw(). \n";
}
private:
int x1_;
int y1_;
int x2_;
int y2_;
};
// Adapter wrapper
class RectangleAdapter: public Rectangle, private LegacyRectangle
{
public:
RectangleAdapter(int x, int y, int w, int h):
LegacyRectangle(x, y, x + w, y + h) {
std::cout << "RectangleAdapter(x,y,x+w,x+h)\n";
}
void draw() {
std::cout << "RectangleAdapter: draw().\n";
oldDraw();
}
};
int main()
{
int x = 20, y = 50, w = 300, h = 200;
Rectangle *r = new RectangleAdapter(x,y,w,h);
r->draw();
}
//Output:
//LegacyRectangle(x1,y1,x2,y2)
//RectangleAdapter(x,y,x+w,x+h)
2. The target is the Rectangle class. This is what the client invokes method on.
https://riptutorial.com/ 203
class RectangleAdapter: public Rectangle, private LegacyRectangle {
...
}
5. The LegacyRectangle class does not have the same methods (draw()) as Rectangle, but the
Adapter(RectangleAdapter) can take the Rectangle method calls and turn around and invoke
method on the LegacyRectangle, oldDraw().
void draw() {
std::cout << "RectangleAdapter: draw().\n";
oldDraw();
}
};
Adapter design pattern translates the interface for one class into a compatible but different
interface. So, this is similar to the proxy pattern in that it's a single-component wrapper. But the
interface for the adapter class and the original class may be different.
As we've seen in the example above, this adapter pattern is useful to expose a different interface
for an existing API to allow it to work with other code. Also, by using adapter pattern, we can take
heterogeneous interfaces, and transform them to provide consistent API.
Bridge pattern has a structure similar to an object adapter, but Bridge has a different intent: It is
meant to separate an interface from its implementation so that they can be varied easily and
independently. An adapter is meant to change the interface of an existing object.
Factory Pattern
Factory pattern decouples object creation and allows creation by name using a common interface:
class Animal{
public:
virtual std::shared_ptr<Animal> clone() const = 0;
virtual std::string getname() const = 0;
};
https://riptutorial.com/ 204
{
return "bear";
}
};
class AnimalFactory{
public:
static std::shared_ptr<Animal> getAnimal( const std::string& name )
{
if ( name == "bear" )
return std::make_shared<Bear>();
if ( name == "cat" )
return std::shared_ptr<Cat>();
return nullptr;
}
};
The Builder Pattern decouples the creation of the object from the object itself. The main idea
behind is that an object does not have to be responsible for its own creation. The correct and
valid assembly of a complex object may be a complicated task in itself, so this task can be
delegated to another class.
Inspired by the Email Builder in C#, I've decided to make a C++ version here. An Email object is
not necessarily a very complex object, but it can demonstrate the pattern.
#include <iostream>
#include <sstream>
#include <string>
class Email
{
public:
friend class EmailBuilder; // the builder can access Email's privates
https://riptutorial.com/ 205
static EmailBuilder make();
private:
Email() = default; // restrict construction to builder
string m_from;
string m_to;
string m_subject;
string m_body;
};
class EmailBuilder
{
public:
EmailBuilder& from(const string &from) {
m_email.m_from = from;
return *this;
}
operator Email&&() {
return std::move(m_email); // notice the move
}
private:
Email m_email;
};
EmailBuilder Email::make()
{
return EmailBuilder();
}
// Bonus example!
std::ostream& operator <<(std::ostream& stream, const Email& email)
{
stream << email.to_string();
return stream;
https://riptutorial.com/ 206
}
int main()
{
Email mail = Email::make().from("[email protected]")
.to("[email protected]")
.subject("C++ builders")
.body("I like this API, don't you?");
For older versions of C++, one may just ignore the std::move operation and remove the && from
the conversion operator (although this will create a temporary copy).
The builder finishes its work when it releases the built email by the operator Email&&(). In this
example, the builder is a temporary object and returns the email before being destroyed. You
could also use an explicit operation like Email EmailBuilder::build() {...} instead of the
conversion operator.
int main()
{
EmailBuilder builder;
add_addresses(builder);
compose_mail(builder);
https://riptutorial.com/ 207
You can change the design of this pattern to fit your needs. I'll give one variant.
In the given example the Email object is immutable, i.e., it's properties can't be modified because
there is no access to them. This was a desired feature. If you need to modify the object after its
creation you have to provide some setters to it. Since those setters would be duplicated in the
builder, you may consider to do it all in one class (no builder class needed anymore).
Nevertheless, I would consider the need to make the built object mutable in the first place.
https://riptutorial.com/ 208
Chapter 38: Digit separators
Examples
Digit Separator
• Pronounce 7237498123.
• Compare 237498123 with 237499123 for equality.
• Decide whether 237499123 or 20249472 is larger.
C++14 define Simple Quotation Mark ' as a digit separator, in numbers and user-defined literals.
This can make it easier for human readers to parse large numbers.
C++14
Example:
• The literals 1048576, 1'048'576, 0X100000, 0x10'0000, and 0'004'000'000 all have the same
value.
• The literals 1.602'176'565e-19 and 1.602176565e-19 have the same value.
The position of the single quotes is irrelevant. All the following are equivalent:
C++14
C++14
https://riptutorial.com/ 209
Chapter 39: Enumeration
Examples
Basic Enumeration Declaration
Standard enumerations allow users to declare a useful name for a set of integers. The names are
collectively referred to as enumerators. An enumeration and its associated enumerators are
defined as follows:
enum myEnum
{
enumName1,
enumName2,
};
An enumeration is a type, one which is distinct from all other types. In this case, the name of this
type is myEnum. Objects of this type are expected to assume the value of an enumerator within the
enumeration.
The enumerators declared within the enumeration are constant values of the type of the
enumeration. Though the enumerators are declared within the type, the scope operator :: is not
needed to access the name. So the name of the first enumerator is enumName1.
C++11
The scope operator can be optionally used to access an enumerator within an enumeration. So
enumName1 can also be spelled myEnum::enumName1.
Enumerators are assigned integer values starting from 0 and increasing by 1 for each enumerator
in an enumeration. So in the above case, enumName1 has the value 0, while enumName2 has the value
1.
Enumerators can also be assigned a specific value by the user; this value must be an integral
constant expression. Enumerators who's values are not explicitly provided will have their value set
to the value of the previous enumerator + 1.
enum myEnum
{
enumName1 = 1, // value will be 1
enumName2 = 2, // value will be 2
enumName3, // value will be 3, previous value + 1
enumName4 = 7, // value will be 7
enumName5, // value will be 8
enumName6 = 5, // value will be 5, legal to go backwards
enumName7 = 3, // value will be 3, legal to reuse numbers
enumName8 = enumName4 + 2, // value will be 9, legal to take prior enums and adjust them
};
https://riptutorial.com/ 210
Enumeration in switch statements
A common use for enumerators is for switch statements and so they commonly appear in state
machines. In fact a useful feature of switch statements with enumerations is that if no default
statement is included for the switch, and not all values of the enum have been utilized, the
compiler will issue a warning.
enum State {
start,
middle,
end
};
...
switch(myState) {
case start:
...
case middle:
...
} // warning: enumeration value 'end' not handled in switch [-Wswitch]
enum E {
Begin,
E1 = Begin,
E2,
// ..
En,
End
};
C++11
https://riptutorial.com/ 211
}
enum E {
E1 = 4,
E2 = 8,
// ..
En
};
std::vector<E> build_all_E()
{
const E all[] = {E1, E2, /*..*/ En};
and then
C++11
enum E {
E1 = 4,
E2 = 8,
// ..
En
};
and then
Scoped enums
C++11 introduces what are known as scoped enums. These are enumerations whose members
must be qualified with enumname::membername. Scoped enums are declared using the enum class
syntax. For example, to store the colors in a rainbow:
https://riptutorial.com/ 212
RED,
ORANGE,
YELLOW,
GREEN,
BLUE,
INDIGO,
VIOLET
};
rainbow r = rainbow::INDIGO;
enum classes cannot be implicitly converted to ints without a cast. So int x = rainbow::RED is
invalid.
Scoped enums also allow you to specify the underlying type, which is the type used to represent a
member. By default it is int. In a Tic-Tac-Toe game, you may store the piece as
As you may notice, enums can have a trailing comma after the last member.
Scoped enumerations:
...
enum class Status; // Forward declaration
Status doWork(); // Use the forward declaration
...
enum class Status { Invalid, Success, Fail };
Status doWork() // Full declaration required for implementation
{
return Status::Success;
}
Unscoped enumerations:
...
enum Status: int; // Forward declaration, explicit type required
Status doWork(); // Use the forward declaration
...
enum Status: int{ Invalid=0, Success, Fail }; // Must match forward declare type
static_assert( Success == 1 );
An in-depth multi-file example can be found here: Blind fruit merchant example
https://riptutorial.com/ 213
Chapter 40: Exceptions
Examples
Catching exceptions
A try/catch block is used to catch exceptions. The code in the try section is the code that may
throw an exception, and the code in the catch clause(s) handles the exception.
#include <iostream>
#include <string>
#include <stdexcept>
int main() {
std::string str("foo");
try {
str.at(10); // access element, may throw std::out_of_range
} catch (const std::out_of_range& e) {
// what() is inherited from std::exception and contains an explanatory message
std::cout << e.what();
}
}
Multiple catch clauses may be used to handle multiple exception types. If multiple catch clauses
are present, the exception handling mechanism tries to match them in order of their appearance
in the code:
std::string str("foo");
try {
str.reserve(2); // reserve extra capacity, may throw std::length_error
str.at(10); // access element, may throw std::out_of_range
} catch (const std::length_error& e) {
std::cout << e.what();
} catch (const std::out_of_range& e) {
std::cout << e.what();
}
Exception classes which are derived from a common base class can be caught with a single catch
clause for the common base class. The above example can replace the two catch clauses for
std::length_error and std::out_of_range with a single clause for std:exception:
std::string str("foo");
try {
str.reserve(2); // reserve extra capacity, may throw std::length_error
str.at(10); // access element, may throw std::out_of_range
} catch (const std::exception& e) {
std::cout << e.what();
}
https://riptutorial.com/ 214
Because the catch clauses are tried in order, be sure to write more specific catch clauses first,
otherwise your exception handling code might never get called:
try {
/* Code throwing exceptions omitted. */
} catch (const std::exception& e) {
/* Handle all exceptions of type std::exception. */
} catch (const std::runtime_error& e) {
/* This block of code will never execute, because std::runtime_error inherits
from std::exception, and all exceptions of type std::exception were already
caught by the previous catch clause. */
}
Another possibility is the catch-all handler, which will catch any thrown object:
try {
throw 10;
} catch (...) {
std::cout << "caught an exception";
}
Sometimes you want to do something with the exception you catch (like write to log or print a
warning) and let it bubble up to the upper scope to be handled. To do so, you can rethrow any
exception you catch:
try {
... // some code here
} catch (const SomeException& e) {
std::cout << "caught an exception";
throw;
}
Using throw; without arguments will re-throw the currently caught exception.
C++11
To rethrow a managed std::exception_ptr, the C++ Standard Library has the rethrow_exception
function that can be used by including the <exception> header in your program.
#include <iostream>
#include <string>
#include <exception>
#include <stdexcept>
https://riptutorial.com/ 215
}
}
int main()
{
std::exception_ptr eptr;
try {
std::string().at(1); // this generates an std::out_of_range
} catch(...) {
eptr = std::current_exception(); // capture
}
handle_eptr(eptr);
} // destructor for std::out_of_range called here, when the eptr is destructed
struct A : public B
{
A() try : B(), foo(1), bar(2)
{
// constructor body
}
catch (...)
{
// exceptions from the initializer list and constructor are caught here
// if no exception is thrown here
// then the caught exception is re-thrown.
}
private:
Foo foo;
Bar bar;
};
void function_with_try_block()
try
{
// try block body
}
catch (...)
{
// catch block body
}
Which is equivalent to
void function_with_try_block()
{
try
{
// try block body
}
https://riptutorial.com/ 216
catch (...)
{
// catch block body
}
}
Note that for constructors and destructors, the behavior is different as the catch block re-throws an
exception anyway (the caught one if there is no other throw in the catch block body).
The function main is allowed to have a function try block like any other function, but main's function
try block will not catch exceptions that occur during the construction of a non-local static variable
or the destruction of any static variable. Instead, std::terminate is called.
struct A
{
~A() noexcept(false) try
{
// destructor body
}
catch (...)
{
// exceptions of destructor body are caught here
// if no exception is thrown here
// then the caught exception is re-thrown.
}
};
Note that, although this is possible, one needs to be very careful with throwing from destructor, as
if a destructor called during stack unwinding throws an exception, std::terminate is called.
In general, it is considered good practice to throw by value (rather than by pointer), but catch by
(const) reference.
try {
// throw new std::runtime_error("Error!"); // Don't do this!
// This creates an exception object
// on the heap and would require you to catch the
// pointer and manage the memory yourself. This can
// cause memory leaks!
throw std::runtime_error("Error!");
} catch (const std::runtime_error& e) {
std::cout << e.what() << std::endl;
}
One reason why catching by reference is a good practice is that it eliminates the need to
reconstruct the object when being passed to the catch block (or when propagating through to other
catch blocks). Catching by reference also allows the exceptions to be handled polymorphically and
avoids object slicing. However, if you are rethrowing an exception (like throw e;, see example
https://riptutorial.com/ 217
below), you can still get object slicing because the throw e; statement makes a copy of the
exception as whatever type is declared:
#include <iostream>
struct BaseException {
virtual const char* what() const { return "BaseException"; }
};
If you are sure that you are not going to do anything to change the exception (like add information
or modify the message), catching by const reference allows the compiler to make optimizations
and can improve performance. But this can still cause object splicing (as seen in the example
above).
Nested exception
C++11
During exception handling there is a common use case when you catch a generic exception from
a low-level function (such as a filesystem error or data transfer error) and throw a more specific
high-level exception which indicates that some high-level operation could not be performed (such
as being unable to publish a photo on Web). This allows exception handling to react to specific
problems with high level operations and also allows, having only error an message, the
programmer to find a place in the application where an exception occurred. Downside of this
solution is that exception callstack is truncated and original exception is lost. This forces
developers to manually include text of original exception into a newly created one.
https://riptutorial.com/ 218
Nested exceptions aim to solve the problem by attaching low-level exception, which describes the
cause, to a high level exception, which describes what it means in this particular case.
#include <stdexcept>
#include <exception>
#include <string>
#include <fstream>
#include <iostream>
struct MyException
{
MyException(const std::string& message) : message(message) {}
std::string message;
};
https://riptutorial.com/ 219
// sample function that catches an exception and wraps it in a nested exception
void run()
{
try {
open_file("nonexistent.file");
} catch(...) {
std::throw_with_nested( std::runtime_error("run() failed") );
}
}
// runs the sample function above and prints the caught exception
int main()
{
try {
run();
} catch(...) {
print_current_exception_with_nested();
}
}
Possible output:
If you work only with exceptions inherited from std::exception, code can even be simplified.
std::uncaught_exceptions
c++17
#include <exception>
#include <string>
#include <iostream>
// ...
~Transaction() {
https://riptutorial.com/ 220
if (uncaughtExceptionCount == std::uncaught_exceptions()) {
Commit(); // May throw.
} else { // current stack unwinding
RollBack();
}
}
private:
std::string message;
int uncaughtExceptionCount = std::uncaught_exceptions();
};
class Foo
{
public:
~Foo() {
try {
Transaction transaction("In ~Foo"); // Commit,
// even if there is an uncaught exception
//...
} catch (const std::exception& e) {
std::cerr << "exception/~Foo:" << e.what() << std::endl;
}
}
};
int main()
{
try {
Transaction transaction("In main"); // RollBack
Foo foo; // ~Foo commit its transaction.
//...
throw std::runtime_error("Error");
} catch (const std::exception& e) {
std::cerr << "exception/main:" << e.what() << std::endl;
}
}
Output:
In ~Foo: Commit
In main: Rollback
exception/main:Error
Custom exception
You shouldn't throw raw values as exceptions, instead use one of the standard exception classes
or make your own.
Having your own exception class inherited from std::exception is a good way to go about it. Here's
a custom exception class which directly inherits from std::exception:
#include <exception>
protected:
https://riptutorial.com/ 221
int error_number; ///< Error number
int error_offset; ///< Error offset
std::string error_message; ///< Error message
public:
/** Destructor.
* Virtual to allow for subclassing.
*/
virtual ~Except() throw () {}
};
try {
throw(Except("Couldn't do what you were expecting", -12, -34));
} catch (const Except& e) {
std::cout<<e.what()
<<"\nError number: "<<e.getErrorNumber()
<<"\nError offset: "<<e.getErrorOffset();
}
https://riptutorial.com/ 222
As you are not only just throwing a dumb error message, also some other values representing
what the error exactly was, your error handling becomes much more efficient and meaningful.
There's an exception class that let's you handle error messages nicely :std::runtime_error
#include <stdexcept>
protected:
public:
/** Destructor.
* Virtual to allow for subclassing.
*/
virtual ~Except() throw () {}
};
Note that I haven't overridden the what() function from the base class (std::runtime_error) i.e we
will be using the base class's version of what(). You can override it if you have further agenda.
https://riptutorial.com/ 223
Chapter 41: Explicit type conversions
Introduction
An expression can be explicitly converted or cast to type T using dynamic_cast<T>, static_cast<T>,
reinterpret_cast<T>, or const_cast<T>, depending on what type of cast is intended.
C++ also supports function-style cast notation, T(expr), and C-style cast notation, (T)expr.
Syntax
• simple-type-specifier ( )
• simple-type-specifier ( expression-list )
• simple-type-specifier braced-init-list
• typename-specifier ( )
• typename-specifier ( expression-list )
• typename-specifier braced-init-list
• dynamic_cast < type-id > ( expression )
• static_cast < type-id > ( expression )
• reinterpret_cast < type-id > ( expression )
• const_cast < type-id > ( expression )
• ( type-id ) cast-expression
Remarks
All six cast notations have one thing in common:
The reinterpret_cast keyword is responsible for performing two different kinds of "unsafe"
conversions:
• The "type punning" conversions, which can be used to access memory of one type as
though it is of a different type.
• Conversions between integer types and pointer types, in either direction.
https://riptutorial.com/ 224
• Any conversion that can be done by a direct initialization, including both implicit conversions
and conversions that call an explicit constructor or conversion function. See here and here
for more details.
• Between arithmetic and enumeration types, and between different enumeration types. See
enum conversions
• From pointer to member of derived class, to pointer to member of base class. The types
pointed to must match. See derived to base conversion for pointers to members
• void* to T*.
C++11
Examples
Base to derived conversion
A pointer to base class can be converted to a pointer to derived class using static_cast.
static_cast does not do any run-time checking and can lead to undefined behaviour when the
pointer does not actually point to the desired type.
Likewise, a reference to base class can be converted to a reference to derived class using
static_cast.
If the source type is polymorphic, dynamic_cast can be used to perform a base to derived
https://riptutorial.com/ 225
conversion. It performs a run-time check and failure is recoverable instead of producing undefined
behaviour. In the pointer case, a null pointer is returned upon failure. In the reference case, an
exception is thrown upon failure of type std::bad_cast (or a class derived from std::bad_cast).
A pointer to a const object can be converted to a pointer to non-const object using the const_cast
keyword. Here we use const_cast to call a function that is not const-correct. It only accepts a non-
const char* argument even though it never writes through the pointer:
void bad_strlen(char*);
const char* s = "hello, world!";
bad_strlen(s); // compile error
bad_strlen(const_cast<char*>(s)); // OK, but it's better to make bad_strlen accept const char*
const_cast to reference type can be used to convert a const-qualified lvalue into a non-const-
qualified value.
const_cast is dangerous because it makes it impossible for the C++ type system to prevent you
from trying to modify a const object. Doing so results in undefined behavior.
A pointer (resp. reference) to an object type can be converted to a pointer (resp. reference) to any
other object type using reinterpret_cast. This does not call any constructors or conversion
functions.
int x = 42;
char* p = static_cast<char*>(&x); // error: static_cast cannot perform this conversion
char* p = reinterpret_cast<char*>(&x); // OK
*p = 'z'; // maybe this modifies x (see below)
C++11
The result of reinterpret_cast represents the same address as the operand, provided that the
address is appropriately aligned for the destination type. Otherwise, the result is unspecified.
int x = 42;
char& r = reinterpret_cast<char&>(x);
https://riptutorial.com/ 226
const void* px = &x;
const void* pr = &r;
assert(px == pr); // should never fire
C++11
The result of reinterpret_cast is unspecified, except that a pointer (resp. reference) will survive a
round trip from the source type to the destination type and back, as long as the destination type's
alignment requirement is not stricter than that of the source type.
int x = 123;
unsigned int& r1 = reinterpret_cast<unsigned int&>(x);
int& r2 = reinterpret_cast<int&>(r1);
r2 = 456; // sets x to 456
On most implementations, reinterpret_cast does not change the address, but this requirement
was not standardized until C++11.
An object pointer (including void*) or function pointer can be converted to an integer type using
reinterpret_cast. This will only compile if the destination type is long enough. The result is
implementation-defined and typically yields the numeric address of the byte in memory that the
pointer pointers to.
Typically, long or unsigned long is long enough to hold any pointer value, but this is not guaranteed
by the standard.
C++11
If the types std::intptr_t and std::uintptr_t exist, they are guaranteed to be long enough to hold
a void* (and hence any pointer to object type). However, they are not guaranteed to be long
enough to hold a function pointer.
Similarly, reinterpret_cast can be used to convert an integer type into a pointer type. Again the
result is implementation-defined, but a pointer value is guaranteed to be unchanged by a round
trip through an integer type. The standard does not guarantee that the value zero is converted to a
null pointer.
https://riptutorial.com/ 227
long x;
std::cin >> x;
register_callback(my_callback,
reinterpret_cast<void*>(x)); // hopefully this doesn't lose information...
A conversion that involves calling an explicit constructor or conversion function can't be done
implicitly. We can request that the conversion be done explicitly using static_cast. The meaning is
the same as that of a direct initialization, except that the result is a temporary.
class C {
std::unique_ptr<int> p;
public:
explicit C(int* p) : p(p) {}
};
void f(C c);
void g(int* p) {
f(p); // error: C::C(int*) is explicit
f(static_cast<C>(p)); // ok
f(C(p)); // equivalent to previous line
C c(p); f(c); // error: C is not copyable
}
Implicit conversion
static_cast can perform any implicit conversion. This use of static_cast can occasionally be
useful, such as in the following examples:
• When passing arguments to an ellipsis, the "expected" argument type is not statically known,
so no implicit conversion will occur.
Without the explicit type conversion, a double object would be passed to the ellipsis, and
undefined behaviour would occur.
• A derived class assignment operator can call a base class assignment operator like so:
https://riptutorial.com/ 228
Enum conversions
static_castcan convert from an integer or floating point type to an enumeration type (whether
scoped or unscoped), and vice versa. It can also convert between enumeration types.
C++11
○ If the enum's value can be represented exactly in the destination type, the result is that
value.
○ Otherwise, if the destination type is an integer type, the result is unspecified.
○ Otherwise, if the destination type is a floating point type, the result is the same as that
of converting to the underlying type and then to the floating point type.
Example:
○ If the original value is within the destination enum's range, the result is that value. Note
that this value might be unequal to all enumerators.
○ Otherwise, the result is unspecified (<= C++14) or undefined (>= C++17).
Example:
enum Scale {
SINGLE = 1,
DOUBLE = 2,
QUAD = 4
};
Scale s1 = 1; // error
Scale s2 = static_cast<Scale>(2); // s2 is DOUBLE
Scale s3 = static_cast<Scale>(3); // s3 has value 3, and is not equal to any enumerator
Scale s9 = static_cast<Scale>(9); // unspecified value in C++14; UB in C++17
C++11
• When a floating point type is converted to an enumeration type, the result is the same as
https://riptutorial.com/ 229
converting to the enum's underlying type and then to the enum type.
enum Direction {
UP = 0,
LEFT = 1,
DOWN = 2,
RIGHT = 3,
};
Direction d = static_cast<Direction>(3.14); // d is RIGHT
A pointer to member of derived class can be converted to a pointer to member of base class using
static_cast. The types pointed to must match.
If the operand is a null pointer to member value, the result is also a null pointer to member value.
Otherwise, the conversion is only valid if the member pointed to by the operand actually exists in
the destination class, or if the destination class is a base or derived class of the class containing
the member pointed to by the operand. static_cast does not check for validity. If the conversion is
not valid, the behaviour is undefined.
struct A {};
struct B { int x; };
struct C : A, B { int y; double z; };
int B::*p1 = &B::x;
int C::*p2 = p1; // ok; implicit conversion
int B::*p3 = p2; // error
int B::*p4 = static_cast<int B::*>(p2); // ok; p4 is equal to p1
int A::*p5 = static_cast<int A::*>(p2); // undefined; p2 points to x, which is a member
// of the unrelated class B
double C::*p6 = &C::z;
double A::*p7 = static_cast<double A::*>(p6); // ok, even though A doesn't contain z
int A::*p8 = static_cast<int A::*>(p6); // error: types don't match
void* to T*
In C++, void* cannot be implicitly converted to T* where T is an object type. Instead, static_cast
should be used to perform the conversion explicitly. If the operand actually points to a T object, the
result points to that object. Otherwise, the result is unspecified.
C++11
Even if the operand does not point to a T object, as long as the operand points to a byte whose
address is properly aligned for the type T, the result of the conversion points to the same byte.
https://riptutorial.com/ 230
const void* p1 = &c;
const char* p2 = p1; // error
const char* p3 = static_cast<const char*>(p1); // ok; p3 points to c
const int* p4 = static_cast<const int*>(p1); // unspecified in C++03;
// possibly unspecified in C++11 if
// alignof(int) > alignof(char)
char* p5 = static_cast<char*>(p1); // error: casting away constness
C-style casting
C-Style casting can be considered 'Best effort' casting and is named so as it is the only cast which
could be used in C. The syntax for this cast is (NewType)variable.
Whenever this cast is used, it uses one of the following c++ casts (in order):
• const_cast<NewType>(variable)
• static_cast<NewType>(variable)
• const_cast<NewType>(static_cast<const NewType>(variable))
• reinterpret_cast<const NewType>(variable)
• const_cast<NewType>(reinterpret_cast<const NewType>(variable))
Functional casting is very similar, though as a few restrictions as the result of its syntax:
NewType(expression). As a result, only types without spaces can be cast to.
It's better to use new c++ cast, because s more readable and can be spotted easily anywhere
inside a C++ source code and errors will be detected in compile-time, instead in run-time.
https://riptutorial.com/ 231
Chapter 42: Expression templates
Examples
Basic expression templates on element-wise algebraic expressions
Expression templates (denoted as ETs in the following) are a powerful template meta-
programming technique, used to speed-up calculations of sometimes quite expensive
expressions. It is widely used in different domains, for example in implementation of linear algebra
libraries.
For this example, consider the context of linear algebraic computations. More specifically,
computations involving only element-wise operations. This kind of computations are the most
basic applications of ETs, and they serve as a good introduction to how ETs work internally.
Here for the sake of simplicity, I'll assume that the class Vector and operation + (vector plus:
element-wise plus operation) and operation * (here means vector inner product: also element-wise
operation) are both correctly implemented, as how they should be, mathematically.
In a conventional implementation without using ETs (or other similar techniques), at least five
constructions of Vector instances take place in order to obtain the final result:
Implementation using ETs can eliminate the creation of temporary Vector _tmp in 2, thus leaving
only four constructions of Vector instances. More interestingly, consider the following expression
which is more complex:
There will also be four constructions of Vector instances in total: vec_1, vec_2, vec_3 and result. In
other words, in this example, where only element-wise operations are involved, it is
https://riptutorial.com/ 232
guaranteed that no temporary objects will be created from intermediate calculations.
Basically speaking, ETs for any algebraic computations consist of two building blocks:
So, specifically how do we implement ETs in this example? Let's walk through it now.
The expression to compute result can be decomposed further into two sub-expressions:
• Instead of compute right away each sub-expression, ETs first model the whole expression
using a graphical structure. Each node in the graph represents a PAE. The edge connection
of the nodes represent the actual computation flow. So for the above expression, we obtain
the following graph:
• The final computation is implemented by looking through the graph hierarchy: since here
https://riptutorial.com/ 233
we are dealing with only element-wise operations, the computation of each indexed value
in result can be done independently: the final evaluation of result can be lazily postponed
to a element-wise evaluation of each element of result. In other words, since the
computation of an element of result, elem_res, can be expressed using corresponding
elements in vec_1 (elem_1), vec_2 (elem_2) and vec_3 (elem_3) as:
there is therefore no need to create a temporary Vector to store the result of intermediate inner
product: the whole computation for one element can be done altogether, and be encoded
inside the indexed-access operation.
#ifndef EXPR_VEC
# define EXPR_VEC
# include <vector>
# include <cassert>
# include <utility>
# include <iostream>
# include <algorithm>
# include <functional>
///
/// This is a wrapper for std::vector. It's only purpose is to print out a log when a
/// vector constructions in called.
/// It wraps the indexed access operator [] and the size() method, which are
/// important for later ETs implementation.
///
// std::vector wrapper.
template<typename ScalarType> class Vector
{
public:
explicit Vector() { std::cout << "ctor called.\n"; };
explicit Vector(int size): _vec(size) { std::cout << "ctor called.\n"; };
explicit Vector(const std::vector<ScalarType> &vec): _vec(vec)
{ std::cout << "ctor called.\n"; };
https://riptutorial.com/ 234
decltype(auto) operator[](int indx) { return _vec[indx]; }
decltype(auto) operator[](int indx) const { return _vec[indx]; }
private:
std::vector<ScalarType> _vec;
};
///
/// These are conventional overloads of operator + (the vector plus operation)
/// and operator * (the vector inner product operation) without using the expression
/// templates. They are later used for bench-marking purpose.
///
std::vector<ScalarType> _vec;
_vec.resize(lhs().size());
std::transform(std::cbegin(lhs()), std::cend(lhs()),
std::cbegin(rhs()), std::begin(_vec),
std::plus<>());
return Vector<ScalarType>(std::move(_vec));
}
std::vector<ScalarType> _vec;
_vec.resize(lhs().size());
std::transform(std::cbegin(lhs()), std::cend(lhs()),
std::cbegin(rhs()), std::begin(_vec),
std::multiplies<>());
return Vector<ScalarType>(std::move(_vec));
}
#endif //!EXPR_VEC
https://riptutorial.com/ 235
Let's break it down to sections.
1. Section 1 implements a base class for all expressions. It employs the Curiously Recurring
Template Pattern (CRTP).
2. Section 2 implements the first PAE: a terminal, which is just a wrapper (const reference) of
an input data structure containing real input value for computation.
3. Section 3 implements the second PAE: binary_operation, which is a class template later
used for vector_plus and vector_innerprod. It's parametrized by the type of operation, the
left-hand-side PAE and the right-hand-side PAE. The actual computation is encoded in
the indexed-access operator.
4. Section 4 defines vector_plus and vector_innerprod operations as element-wise operation.
It also overload operator + and * for PAEs: such that these two operations also return PAE.
#ifndef EXPR_EXPR
# define EXPR_EXPR
namespace expr
{
/// -----------------------------------------
///
/// Section 1.
///
/// The first section is a base class template for all kinds of expression. It
/// employs the Curiously Recurring Template Pattern, which enables its instantiation
/// to any kind of expression structure inheriting from it.
///
/// -----------------------------------------
protected:
explicit expr_base() {};
int size() const { return self().size_impl(); }
auto operator[](int indx) const { return self().at_impl(indx); }
auto operator()() const { return self()(); };
};
/// -----------------------------------------
///
/// The following section 2 & 3 are abstractions of pure algebraic expressions (PAE).
/// Any PAE can be converted to a real object instance using operator(): it is in
/// this conversion process, where the real computations are done.
///
https://riptutorial.com/ 236
/// Section 2. Terminal
///
/// A terminal is an abstraction wrapping a const reference to the Vector data
/// structure. It inherits from expr_base, therefore providing a unified interface
/// wrapping a Vector into a PAE.
///
/// It provides the size() method, indexed access through at_impl() and a conversion
/// to referenced object through () operator.
///
/// It might no be necessary for user defined data structures to have a terminal
/// wrapper, since user defined structure can inherit expr_base, therefore eliminates
/// the need to provide such terminal wrapper.
///
/// -----------------------------------------
private:
const DataType &_val;
};
/// -----------------------------------------
///
/// Section 3. Binary operation expression.
///
/// This is a PAE abstraction of any binary expression. Similarly it inherits from
/// expr_base.
///
/// It provides the size() method, indexed access through at_impl() and a conversion
/// to referenced object through () operator. Each call to the at_impl() method is
/// a element wise computation.
///
/// -----------------------------------------
explicit binary_ops(const Ops &ops, const lExpr &lxpr, const rExpr &rxpr)
: _ops(ops), _lxpr(lxpr), _rxpr(rxpr) {};
https://riptutorial.com/ 237
int size_impl() const { return _lxpr.size(); };
/// -----------------------------------------
/// Section 4.
///
/// The following two structs defines algebraic operations on PAEs: here only vector
/// plus and vector inner product are implemented.
///
/// First, some element-wise operations are defined : in other words, vec_plus and
/// vec_prod acts on elements in Vectors, but not whole Vectors.
///
/// Then, operator + & * are overloaded on PAEs, such that: + & * operations on PAEs
/// also return PAEs.
///
/// -----------------------------------------
https://riptutorial.com/ 238
auto operator+(const lExpr &lhs, const rExpr &rhs)
{ return binary_ops<vec_plus_t,lExpr,rExpr>(vec_plus,lhs,rhs); }
} //!expr
#endif //!EXPR_EXPR
# include <chrono>
# include <iomanip>
# include <iostream>
# include "vec.hh"
# include "expr.hh"
# include "boost/core/demangle.hpp"
int main()
{
using dtype = float;
constexpr int size = 5e7;
std::vector<dtype> _vec1(size);
std::vector<dtype> _vec2(size);
std::vector<dtype> _vec3(size);
Vector<dtype> vec1(std::move(_vec1));
Vector<dtype> vec2(std::move(_vec2));
Vector<dtype> vec3(std::move(_vec3));
https://riptutorial.com/ 239
expr::terminal<Vector<dtype>> vec4(vec1);
expr::terminal<Vector<dtype>> vec5(vec2);
expr::terminal<Vector<dtype>> vec6(vec3);
return 0;
}
Here's one possible output when compiled with -O3 -std=c++14 using GCC 5.3:
ctor called.
ctor called.
ctor called.
• Using ETs achieves rather significant performance boost in this case ( > 3x).
• Creation of temporary Vector object is eliminated. As in the ETs case, ctor is called only
once.
• Boost::demangle was used to visualize the type of ETs return before conversion: it clearly
constructed exactly the same expression graph demonstrated above.
• An obvious disadvantage of ETs is the learning curve, the complexity of implementation and
code-maintenance difficulty. In the above example where only element-wise operations are
considered, the implementation contains already enormous amount of boilerplates, let alone
https://riptutorial.com/ 240
in real world, where more complex algebraic expressions occur in every computation and
element-wise independence no longer hold (for example matrix multiplication), the difficulty
will be exponential.
• Another caveat of using ETs is that they do play well with the auto keyword. As mentioned
above, PAEs are essentially proxies: and proxies basically do not play well with auto.
Consider the following example:
Here in each iteration of the for loop, result will be re-evaluated, since the expression graph
instead of the computed value is passed to the for loop.
• boost::proto is a powerful library letting you define your own rules & grammars for your own
expressions and execute using ETs.
• Eigen is a library for linear algebra that implements various algebraic computations
efficiently using ETs.
Before actually diving into expression templates, you should understand why you need them in the
first place. To illustrate this, consider the very simple Matrix class given below:
https://riptutorial.com/ 241
private:
std::vector<T> values;
};
Given the previous class definition, you can now write Matrix expressions such as:
// initialize a, b & c
for (std::size_t y = 0; y != rows; ++y) {
for (std::size_t x = 0; x != cols; ++x) {
a(x, y) = 1.0;
b(x, y) = 2.0;
c(x, y) = 3.0;
}
}
As illustrated above, being able to overload operator+() provides you with a notation which mimics
the natural mathematical notation for matrices.
To understand why, you have to consider what happens when you write an expression such as
Matrix d = a + b + c. This in fact expands to ((a + b) + c) or operator+(operator+(a, b), c). In
other words, the loop inside operator+() is executed twice, whereas it could have been easily
performed in a single pass. This also results in 2 temporaries being created, which further
degrades performance. In essence, by adding the flexibility to use a notation close to its
mathematical counterpart, you have also made the Matrix class highly inefficient.
For example, without operator overloading, you could implement a far more efficient Matrix
summation using a single pass:
https://riptutorial.com/ 242
const Matrix<T, COL, ROW>& c)
{
Matrix<T, COL, ROW> result;
for (size_t y = 0; y != ROW; ++y) {
for (size_t x = 0; x != COL; ++x) {
result(x, y) = a(x, y) + b(x, y) + c(x, y);
}
}
return result;
}
The previous example however has its own disadvantages because it creates a far more
convoluted interface for the Matrix class (you would have to consider methods such as
Matrix::add2(), Matrix::AddMultiply() and so on).
Instead let us take a step back and see how we can adapt operator overloading to perform in a
more efficient way
The problem stems from the fact that the expression Matrix d = a + b + c is evaluated too
"eagerly" before you have had an opportunity to build the entire expression tree. In other words,
what you really want to achieve is to evaluate a + b + c in one pass and only once you actually
need to assign the resulting expressing to d.
This is the core idea behind expression templates: instead of having operator+() evaluate
immediately the result of adding two Matrix instances, it will return an "expression template" for
future evaluation once the entire expression tree has been built.
For example, here is a possible implementation for an expression template corresponding to the
summation of 2 types:
As you can see, operator+() no longer returns an "eager evaluation" of the result of adding 2
https://riptutorial.com/ 243
Matrix instances (which would be another Matrix instance), but instead an expression template
representing the addition operation. The most important point to keep in mind is that the
expression has not been evaluated yet. It merely holds references to its operands.
In fact, nothing stops you from instantiating the MatrixSum<> expression template as follows:
You can however at a later stage, when you actually need the result of the summation, evaluate
the expression d = a + b as follows:
As you can see, another benefit of using an expression template, is that you have basically
managed to evaluate the sum of a and b and assign it to d in a single pass.
Also, nothing stops you from combining multiple expression templates. For example, a + b + c
would result in the following expression template:
And here again you can evaluate the final result using a single pass:
Finally, the last piece of the puzzle is to actually plug your expression template into the Matrix
class. This is essentially achieved by providing an implementation for Matrix::operator=(), which
takes the expression template as an argument and evaluates it in one pass, as you did "manually"
before:
https://riptutorial.com/ 244
Matrix<T, COL, ROW>& operator=(const E& expression) {
for (std::size_t y = 0; y != rows(); ++y) {
for (std::size_t x = 0; x != cols(); ++x) {
values[y * COL + x] = expression(x, y);
}
}
return *this;
}
private:
std::vector<T> values;
};
https://riptutorial.com/ 245
Chapter 43: File I/O
Introduction
C++ file I/O is done via streams. The key abstractions are:
Streams use std::locale, e.g., for details of the formatting and for translation between external
encodings and the internal encoding.
Examples
Opening a file
Opening a file is done in the same way for all 3 file streams (ifstream, ofstream, and fstream).
std::fstream iofs("foo.txt"); // fstream: Opens file "foo.txt" for reading and writing.
Alternatively, you can use the file stream's member function open():
std::ifstream ifs;
ifs.open("bar.txt"); // ifstream: Opens file "bar.txt" for reading only.
std::ofstream ofs;
ofs.open("bar.txt"); // ofstream: Opens file "bar.txt" for writing only.
std::fstream iofs;
iofs.open("bar.txt"); // fstream: Opens file "bar.txt" for reading and writing.
You should always check if a file has been opened successfully (even when writing). Failures can
include: the file doesn't exist, file hasn't the right access rights, file is already in use, disk errors
occurred, drive disconnected ... Checking can be done as follows:
https://riptutorial.com/ 246
// Try to read the file 'foo.txt'.
std::ifstream ifs("fooo.txt"); // Note the typo; the file can't be opened.
When file path contains backslashes (for example, on Windows system) you should properly
escape them:
C++11
C++11
If you want to open file with non-ASCII characters in path on Windows currently you can use non-
standard wide character path argument:
If you know how the data is formatted, you can use the stream extraction operator (>>). Let's
assume you have a file named foo.txt which contains the following data:
Then you can use the following code to read that data from the file:
// Define variables.
std::ifstream is("foo.txt");
std::string firstname, lastname;
int age, bmonth, bday, byear;
https://riptutorial.com/ 247
// Extract firstname, lastname, age, bday month, bday day, and bday year in that order.
// Note: '>>' returns false if it reached EOF (end of file) or if the input data doesn't
// correspond to the type of the input variable (for example, the string "foo" can't be
// extracted into an 'int' variable).
while (is >> firstname >> lastname >> age >> bmonth >> bday >> byear)
// Process the data that has been read.
The stream extraction operator >> extracts every character and stops if it finds a character that
can't be stored or if it is a special character:
This means that the following version of the file foo.txt will also be successfully read by the
previous code:
John
Doe 25
4 6 1987
Jane
Doe
15 5
24
1976
The stream extraction operator >> always returns the stream given to it. Therefore, multiple
operators can be chained together in order to read data consecutively. However, a stream can
also be used as a Boolean expression (as shown in the while loop in the previous code). This is
because the stream classes have a conversion operator for the type bool. This bool() operator will
return true as long as the stream has no errors. If a stream goes into an error state (for example,
because no more data can be extracted), then the bool() operator will return false. Therefore, the
while loop in the previous code will be exited after the input file has been read to its end.
If you wish to read an entire file as a string, you may use the following code:
// Opens 'foo.txt'.
std::ifstream is("foo.txt");
std::string whole_file;
https://riptutorial.com/ 248
This code reserves space for the string in order to cut down on unneeded memory allocations.
If you want to read a file line by line, you can use the function getline():
std::ifstream is("foo.txt");
If you want to read a fixed number of characters, you can use the stream's member function read()
:
std::ifstream is("foo.txt");
char str[4];
After executing a read command, you should always check if the error state flag failbit has been
set, as it indicates whether the operation failed or not. This can be done by calling the file stream's
member function fail():
if (is.fail())
// Failed to read!
Writing to a file
There are several ways to write to a file. The easiest way is to use an output file stream (ofstream)
together with the stream insertion operator (<<):
std::ofstream os("foo.txt");
if(os.is_open()){
os << "Hello World!";
}
Instead of <<, you can also use the output file stream's member function write():
std::ofstream os("foo.txt");
if(os.is_open()){
char data[] = "Foo";
After writing to a stream, you should always check if error state flag badbit has been set, as it
indicates whether the operation failed or not. This can be done by calling the output file stream's
member function bad():
https://riptutorial.com/ 249
os << "Hello Badbit!"; // This operation might fail for any reason.
if (os.bad())
// Failed to write!
Opening modes
When creating a file stream, you can specify an opening mode. An opening mode is basically a
setting to control how the stream opens the file.
An opening mode can be provided as second parameter to the constructor of a file stream or to its
open() member function:
std::ifstream is;
is.open("foo.txt", std::ios::in | std::ios::binary);
It is to be noted that you have to set ios::in or ios::out if you want to set other flags as they are
not implicitly set by the iostream members although they have a correct default value.
If you don't specify an opening mode, then the following default modes are used:
• ifstream - in
• ofstream - out
• fstream - in and out
The file opening modes that you may specify by design are:
ate at end Input Goes to the end of the file when opening.
Note: Setting the binary mode lets the data be read/written exactly as-is; not setting it enables the
translation of the newline '\n' character to/from a platform specific end of line sequence.
https://riptutorial.com/ 250
Closing a file
Explicitly closing a file is rarely necessary in C++, as a file stream will automatically close its
associated file in its destructor. However, you should try to limit the lifetime of a file stream object,
so that it does not keep the file handle open longer than necessary. For example, this can be done
by putting all file operations into an own scope ({}):
// Write data.
output << prepared_data;
} // The ofstream will go out of scope here.
// Its destructor will take care of closing the file properly.
Calling close() explicitly is only necessary if you want to reuse the same fstream object later, but
don't want to keep the file open in between:
// Preparing data might take a long time. Therefore, we don't open the output file stream
// before we actually can write some data to it.
std::string const more_prepared_data = prepare_complex_data();
// Open the file "foo.txt" for the second time once we are ready for writing.
output.open("foo.txt");
Flushing a stream
File streams are buffered by default, as are many other types of streams. This means that writes
to the stream may not cause the underlying file to change immediately. In oder to force all buffered
writes to take place immediately, you can flush the stream. You can do this either directly by
invoking the flush() method or through the std::flush stream manipulator:
std::ofstream os("foo.txt");
os << "Hello World!" << std::flush;
https://riptutorial.com/ 251
char data[3] = "Foo";
os.write(data, 3);
os.flush();
There is a stream manipulator std::endl that combines writing a newline with flushing the stream:
Buffering can improve the performance of writing to a stream. Therefore, applications that do a lot
of writing should avoid flushing unnecessarily. Contrary, if I/O is done infrequently, applications
should consider flushing frequently in order to avoid data getting stuck in the stream object.
std::ifstream f("file.txt");
if (f)
{
std::stringstream buffer;
buffer << f.rdbuf();
f.close();
The rdbuf() method returns a pointer to a streambuf that can be pushed into buffer via the
stringstream::operator<< member function.
std::ifstream f("file.txt");
if (f)
{
std::string str((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
// Operations on `str`...
}
This is nice because requires little code (and allows reading a file directly into any STL container,
not only strings) but can be slow for big files.
NOTE: the extra parentheses around the first argument to the string constructor are essential to
prevent the most vexing parse problem.
https://riptutorial.com/ 252
std::ifstream f("file.txt");
if (f)
{
f.seekg(0, std::ios::end);
const auto size = f.tellg();
// Operations on `str`...
}
In the example below we use std::string and operator>> to read items from the file.
std::ifstream file("file3.txt");
std::vector<std::string> v;
std::string s;
while(file >> s) // keep reading until we run out
{
v.push_back(s);
}
In the above example we are simply iterating through the file reading one "item" at a time using
operator>>. This same affect can be achieved using the std::istream_iterator which is an input
iterator that reads one "item" at a time from the stream. Also most containers can be constructed
using two iterators so we can simplify the above code to:
std::ifstream file("file3.txt");
std::vector<std::string> v(std::istream_iterator<std::string>{file},
std::istream_iterator<std::string>{});
We can extend this to read any object types we like by simply specifying the object we want to
read as the template parameter to the std::istream_iterator. Thus we can simply extend the
above to read lines (rather than words) like this:
https://riptutorial.com/ 253
// Read a line from a stream.
friend std::istream& operator>>(std::istream& stream, Line& line)
{
return std::getline(stream, line.data);
}
};
std::ifstream file("file3.txt");
C++11
struct info_type
{
std::string name;
int age;
float height;
void func4()
{
auto file = std::ifstream("file4.txt");
std::vector<info_type> v;
for(info_type info; file >> info;) // keep reading until we run out
{
// we only get here if the read succeeded
v.push_back(info);
}
file4.txt
https://riptutorial.com/ 254
Wogger Wabbit
2
6.2
Bilbo Baggins
111
81.3
Mary Poppins
29
154.8
Output:
Copying a file
C++17
With C++17 the standard way to copy a file is including the <filesystem> header and using
copy_file:
std::fileystem::copy_file("source_filename", "dest_filename");
The filesystem library was originally developed as boost.filesystem and finally merged to ISO C++
as of C++17.
eof returns true only after reading the end of file. It does NOT indicate that the next read will be
the end of stream.
while (!f.eof())
{
// Everything is OK
f >> buffer;
https://riptutorial.com/ 255
/* Use `buffer` */
}
while (!f.eof())
{
f >> buffer >> std::ws;
if (f.fail())
break;
/* Use `buffer` */
}
but
Further references:
If you need to write a file using different locale settings to the default, you can use std::locale and
std::basic_ios::imbue() to do that for a specific file stream:
• You should always apply a local to a stream before opening the file.
• Once the stream has been imbued you should not change the locale.
Reasons for Restrictions: Imbuing a file stream with a locale has undefined behavior if the
current locale is not state independent or not pointing at the beginning of the file.
UTF-8 streams (and others) are not state independent. Also a file stream with a UTF-8 locale may
try and read the BOM marker from the file when it is opened; so just opening the file may read
characters from the file and it will not be at the beginning.
#include <iostream>
#include <fstream>
#include <locale>
int main()
{
https://riptutorial.com/ 256
std::cout << "User-preferred locale setting is "
<< std::locale("").name().c_str() << std::endl;
Explicitly switching to the classic "C" locale is useful if your program uses a different default locale
and you want to ensure a fixed standard for reading and writing files. With a "C" preferred locale,
the example writes
78,123.456
78,123.456
78123.456
If, for example, the preferred locale is German and hence uses a different number format, the
example writes
78 123,456
78,123.456
78123.456
https://riptutorial.com/ 257
Chapter 44: Floating Point Arithmetic
Examples
Floating Point Numbers are Weird
The first mistake that nearly every single programmer makes is presuming that this code will work
as intended:
float total = 0;
for(float a = 0; a != 2; a += 0.01f) {
total += a;
}
The novice programmer assumes that this will sum up every single number in the range 0, 0.01,
0.02, 0.03, ..., 1.97, 1.98, 1.99, to yield the result 199—the mathematically correct answer.
1. The program as written never concludes. a never becomes equal to 2, and the loop never
terminates.
2. If we rewrite the loop logic to check a < 2 instead, the loop terminates, but the total ends up
being something different from 199. On IEEE754-compliant machines, it will often sum up to
about 201 instead.
The reason that this happens is that Floating Point Numbers represent Approximations of
their assigned values.
double a = 0.1;
double b = 0.2;
double c = 0.3;
if(a + b == c)
//This never prints on IEEE754-compliant machines
std::cout << "This Computer is Magic!" << std::endl;
else
std::cout << "This Computer is pretty normal, all things considered." << std::endl;
Though what we the programmer see is three numbers written in base10, what the compiler (and
the underlying hardware) see are binary numbers. Because 0.1, 0.2, and 0.3 require perfect
division by 10—which is quite easy in a base-10 system, but impossible in a base-2 system—these
numbers have to be stored in imprecise formats, similar to how the number 1/3 has to be stored in
the imprecise form 0.333333333333333... in base-10.
https://riptutorial.com/ 258
representation of 0.2
double c = 0011111111010011001100110011001100110011001100110011001100110011; //imperfect
representation of 0.3
double a + b = 0011111111010011001100110011001100110011001100110011001100110100; //Note that
this is not quite equal to the "canonical" 0.3!
https://riptutorial.com/ 259
Chapter 45: Flow Control
Remarks
Check out the loops topic for the different kind of loops.
Examples
case
Introduces a case label of a switch statement. The operand must be a constant expression and
match the switch condition in type. When the switch statement is executed, it will jump to the case
label with operand equal to the condition, if any.
char c = getchar();
bool confirmed;
switch (c) {
case 'y':
confirmed = true;
break;
case 'n':
confirmed = false;
break;
default:
std::cout << "invalid response!\n";
abort();
}
switch
The keyword switch is followed by a parenthesized condition and a block, which may contain case
labels and an optional default label. When the switch statement is executed, control will be
transferred either to a case label with a value matching that of the condition, if any, or to the default
label, if any.
The condition must be an expression or a declaration, which has either integer or enumeration
type, or a class type with a conversion function to integer or enumeration type.
char c = getchar();
bool confirmed;
switch (c) {
case 'y':
confirmed = true;
break;
https://riptutorial.com/ 260
case 'n':
confirmed = false;
break;
default:
std::cout << "invalid response!\n";
abort();
}
catch
The catch keyword introduces an exception handler, that is, a block into which control will be
transferred when an exception of compatible type is thrown. The catch keyword is followed by a
parenthesized exception declaration, which is similar in form to a function parameter declaration:
the parameter name may be omitted, and the ellipsis ... is allowed, which matches any type. The
exception handler will only handle the exception if its declaration is compatible with the type of the
exception. For more details, see catching exceptions.
try {
std::vector<int> v(N);
// do something
} catch (const std::bad_alloc&) {
std::cout << "failed to allocate memory for vector!" << std::endl;
} catch (const std::runtime_error& e) {
std::cout << "runtime error: " << e.what() << std::endl;
} catch (...) {
std::cout << "unexpected exception!" << std::endl;
throw;
}
default
In a switch statement, introduces a label that will be jumped to if the condition's value is not equal
to any of the case labels' values.
char c = getchar();
bool confirmed;
switch (c) {
case 'y':
confirmed = true;
break;
case 'n':
confirmed = false;
break;
default:
std::cout << "invalid response!\n";
abort();
}
C++11
Defines a default constructor, copy constructor, move constructor, destructor, copy assignment
operator, or move assignment operator to have its default behaviour.
https://riptutorial.com/ 261
class Base {
// ...
// we want to be able to delete derived classes through Base*,
// but have the usual behaviour for Base's destructor.
virtual ~Base() = default;
};
if
int x;
std::cout << "Please enter a positive number." << std::endl;
std::cin >> x;
if (x <= 0) {
std::cout << "You didn't enter a positive number!" << std::endl;
abort();
}
else
The first substatement of an if statement may be followed by the keyword else. The substatement
after the else keyword will be executed when the condition is falsey (that is, when the first
substatement is not executed).
int x;
std::cin >> x;
if (x%2 == 0) {
std::cout << "The number is even\n";
} else {
std::cout << "The number is odd\n";
}
goto
https://riptutorial.com/ 262
return
If return has an operand, the operand is converted to the function's return type, and the converted
value is returned to the caller.
int f() {
return 42;
}
int x = f(); // x is 42
int g() {
return 3.14;
}
int y = g(); // y is 3
If return does not have an operand, the function must have void return type. As a special case, a
void-returning function can also return an expression if the expression has type void.
void f(int x) {
if (x < 0) return;
std::cout << sqrt(x);
}
int g() { return 42; }
void h() {
return f(); // calls f, then returns
return g(); // ill-formed
}
When main returns, std::exit is implicitly called with the return value, and the value is thus
returned to the execution environment. (However, returning from main destroys automatic local
variables, while calling std::exit directly does not.)
throw
1. When throw occurs in an expression with an operand, its effect is to throw an exception,
which is a copy of the operand.
https://riptutorial.com/