0928 Modern C Tutorial
0928 Modern C Tutorial
Changkun Ou ([email protected])
Notice
The content in this PDF file may outdated, please check our website or GitHub repository for the latest
book updates.
License
This work was written by Ou Changkun and licensed under a Creative Commons
Attribution-NonCommercial-NoDerivatives 4.0 International License.
http://creativecommons.org/licenses/by-nc-nd/4.0/
1
2
CONTENTS CONTENTS
Contents
Preface 8
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Targets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.1 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
nullptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
constexpr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
if-switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Initializer list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Structured binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
auto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
decltype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
decltype(auto) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
if constexpr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.5 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3
CONTENTS CONTENTS
Extern templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
The “>” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Variadic templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Fold expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.6 Object-oriented . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Delegate constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Inheritance constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
override . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Generic Lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
std::function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Move semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Perfect forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4
CONTENTS CONTENTS
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Chapter 04 Containers 48
std::array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
std::forward_list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.3 Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Basic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Runtime Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5.2 std::shared_ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.3 std::unique_ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.4 std::weak_ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Ordinary characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Special characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Quantifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5
CONTENTS CONTENTS
7.3 Future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Atomic Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Concistency Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Memory Orders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
8.2 std::filesystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
9.3 Literal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Custom Literal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6
CONTENTS CONTENTS
Contract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Coroutine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Further Readings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Common Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Coding Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Overall Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Code Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Maintainability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Portability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7
PREFACE
Preface
Introduction
C++ user group is a fairly large. From the advent of C++98 to the official finalization of C++11,
it has accumulated over a decade. C++14/17 is an important complement and optimization for C++11,
and C++20 brings this language to the door of modernization. The extended features of all these new
standards are given to the C++ language. Infused with new vitality. C++ programmers, who are still
using traditional C++ (this book refers to C++98 and its previous C++ standards as traditional
C++), may even amzed by the fact that they are not using the same language while reading modern
C++ code.
Modern C++ (this book refers to C++11/14/17/20) introduces a lot of features into traditional
C++, which makes the whole C++ become language that modernized. Modern C++ not only enhances
the usability of the C++ language itself, but the modification of the auto keyword semantics gives us more
confidence in manipulating extremely complex template types. At the same time, a lot of enhancements
have been made to the language runtime. The emergence of Lambda expressions has made C++ have
the “closure” feature of “anonymous functions”, which is almost in modern programming languages (such
as Python/Swift/.. It has become commonplace, and the emergence of rvalue references has solved the
problem of temporary object efficiency that C++ has long been criticized.
C++17 is the direction that has been promoted by the C++ community in the past three years. It
also points out an important development direction of modern C++ programming. Although it does
not appear as much as C++11, it contains a large number of small and beautiful languages and features
(such as structured binding), and the appearance of these features once again corrects our programming
paradigm in C++.
Modern C++ also adds a lot of tools and methods to its own standard library, such as std::thread
at the level of the language itself, which supports concurrent programming and no longer depends on the
underlying system on different platforms. The API implements cross-platform support at the language
level; std::regex provides full regular expression support and more. C++98 has been proven to be a
very successful “paradigm”, and the emergence of modern C++ further promotes this paradigm, making
C++ a better language for system programming and library development. Concepts provide verification
on the compile-time of template parameters, further enhancing the usability of the language.
In conclusion, as an advocate and practitioner of C++, we always maintain an open mind to accept
new things, and we can promote the development of C++ faster, making this old and novel language
more vibrant.
Targets
• This book assumes that readers are already familiar with traditional C++ (i.e. C++98 or earlier),
at least they do not have any difficulty in reading traditional C++ code. In other words, those who
have long experience in traditional C++ and people who desire to quickly understand the features
8
Purpose CHAPTER 01: TOWARDS MODERN C++
of modern C++ in a short period of time are well suited to read the book;
• This book introduces to a certain extent of the dark magic of modern C++. However, these magics
are very limited, they are not suitable for readers who want to learn advanced C++. The purpose
of this book is offering a quick start for modern C++. Of course, advanced readers can also use
this book to review and examine themselves on modern C++.
Purpose
The book claims “On the Fly”. Its intent is to provide a comprehensive introduction to the relevant
features regarding modern C++ (before 2020s). Readers can choose interesting content according to
the following table of content to learn and quickly familiarize the new features you would like to learn.
Readers should aware that all of these features are not required. It should be leart when you really need
it.
At the same time, instead of grammar-only, the book introduces the historical background as simple
as possible of its technical requirements, which provides great help in understanding why these features
comes out.
In addition, The author would like to encourage that readers should be able to use modern C++
directly in their new projects and migrate their old projects to modern C++ gradually after read the
book.
Code
Each chapter of this book has a lot of code. If you encounter problems when writing your own code
with the introductory features of the book, you might as well read the source code attached to the book.
You can find the book here. All the code organized by chapter, the folder name is the chapter number.
Exercises
There are few exercises At the end of each chapter of the book. It is for testing whether you can
use the knowledge points in the current chapter. You can find the possible answer to the problem from
here. The folder name is the chapter number.
Compilation Environment: This book will use clang++ as the only compiler used, and always
use the -std=c++2a compilation flag in your code.
1 > clang ++ -v
2 Apple LLVM version 10.0.1 (clang -1001.0.46.4)
3 Target : x86_64 -apple - darwin18 .6.0
9
1.1 Deprecated Features CHAPTER 01: TOWARDS MODERN C++
Before learning modern C++, let’s take a look at the main features that have been deprecated since
C++11:
Note: Deprecation is not completely unusable, it is only intended to imply that programmers
will disappear from future standards and should be avoided. However, the deprecated features
are still part of the standard library, and most of the features are actually “permanently”
reserved for compatibility reasons.
• register keyword is deprecated and can be used but no longer has any practical mean-
ing.
• If a class has a destructor, the properties for which it generates copy constructors and
copy assignment operators are deprecated.
• C language style type conversion is deprecated (ie using (convert_type)) before variables,
and static_cast, reinterpret_cast, const_cast should be used for type conversion.
• In particular, some of the C standard libraries that can be used are deprecated in the
latest C++17 standard, such as <ccomplex>, <cstdalign>, <cstdbool> and <ctgmath> Wait
There are also other features such as parameter binding (C++11 provides std::bind and std::
function), export, and etc. are also deprecated. These features mentioned above If you have never
used or heard of it, please don’t try to understand them. You should move closer to the
new standard and learn new features directly. After all, technology is moving forward.
10
1.2 Compatibilities with C CHAPTER 01: TOWARDS MODERN C++
For some force majeure and historical reasons, we had to use some C code (even old C code) in C++,
for example, Linux system calls. Before the advent of modern C++, most people talked about “what is
the difference between C and C++”. Generally speaking, in addition to answering the object-oriented
class features and the template features of generic programming, there is no other opinion, or even a
direct answer. “Almost” is also a lot of people. The Wayne diagram in Figure 1.2 roughly answers the
C and C++ related compatibility.
From now on, you should have the idea that “C++ is not a superset of C” in your mind (and not
from the beginning, later [References for further reading] (# further reading references) The difference
between C++98 and C99 is given). When writing C++, you should also avoid using program styles such
as void* whenever possible. When you have to use C, you should pay attention to the use of extern "C",
separate the C language code from the C++ code, and then unify the link, for instance:
1 // foo.h
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5
8 #ifdef __cplusplus
9 }
10 #endif
11
1.2 Compatibilities with C CHAPTER 01: TOWARDS MODERN C++
11
12 // foo.c
13 int add(int x, int y) {
14 return x+y;
15 }
16
17 // 1.1. cpp
18 # include "foo.h"
19 # include <iostream >
20 # include <functional >
21
22 int main () {
23 [out = std :: ref(std :: cout << " Result from C code: " << add (1, 2))](){
24 out.get () << ".\n";
25 }();
26 return 0;
27 }
Comple and output the foo.o file, and link the C++ code to the .o file using clang++ (or both
compile to .o and then unlink them together):
1 clang ++ 1.1. cpp foo.o -std=c++2a -o 1.1
4 SOURCE_C = foo.c
5 OBJECTS_C = foo.o
6
9 TARGET = 1.1
10 LDFLAGS_COMMON = -std=c++2a
11
12 all:
13 (C) − c( SOURCE_C )
14 (CXX)( SOURCE_CXX ) (OBJECT SC )( LDFLAGS_COMMON ) -o (T ARGET )clean : rm − rf ∗ .o(
TARGET )
Note: Indentation in Makefile is a tab instead of a space character. If you copy this code di-
rectly into your editor, the tab may be automatically replaced. Please ensure the indentation
12
Further Readings CHAPTER 02: LANGUAGE USABILITY ENHANCEMENTS
If you don’t know the use of Makefile, it doesn’t matter. In this tutorial, you won’t build
code that is written too complicated. You can also read this book by simply using clang++ -
std=c++2a on the command line.
If you are new to modern C++, you probably still don’t understand the following small piece of
code above, namely:
1 [out = std :: ref(std :: cout << " Result from C code: " << add (1, 2))](){
2 out.get () << ".\n";
3 }();
Don’t worry at the moment, we will come to meet them in our later chapters.
Further Readings
When we declare, define a variable or constant, and control the flow of code, object-oriented functions,
template programming, etc., before the runtime, it may happen when writing code or compiler compiling
code. To this end, we usually talk about language usability, which refers to the language behavior
that occurred before the runtime.
2.1 Constants
nullptr
The purpose of nullptr appears to replace NULL. In a sense, traditional C++ treats NULL and 0
as the same thing, depending on how the compiler defines NULL, and some compilers define NULL as
((void*)0) Some will define it directly as 0.
C++ ** does not allow ** to implicitly convert void * to other types. But if the compiler tries to
define NULL as ((void*)0), then in the following code:
C++ without the void * implicit conversion has to define NULL as 0. This still creates a new problem.
Defining NULL to 0 will cause the overloading feature in C++ to be confusing. Consider the following two
foo functions:
13
2.1 Constants CHAPTER 02: LANGUAGE USABILITY ENHANCEMENTS
Then the foo(NULL); statement will call foo(int), which will cause the code to be counterintuitive.
To solve this problem, C++11 introduced the nullptr keyword, which is specifically used to distin-
guish null pointers, 0. The type of nullptr is nullptr_t, which can be implicitly converted to any pointer
or member pointer type, and can be compared equally or unequally with them.
7 int main () {
8 if (std :: is_same < decltype (NULL), decltype (0) >:: value)
9 std :: cout << "NULL == 0" << std :: endl;
10 if (std :: is_same < decltype (NULL), decltype (( void *)0) >:: value)
11 std :: cout << "NULL == (void *)0" << std :: endl;
12 if (std :: is_same < decltype (NULL), std :: nullptr_t >:: value)
13 std :: cout << "NULL == nullptr " << std :: endl;
14
21 void foo(char *) {
22 std :: cout << "foo(char *) is called " << std :: endl;
23 }
24 void foo(int i) {
25 std :: cout << "foo(int) is called " << std :: endl;
26 }
1 foo(int) is called
2 foo(char *) is called
From the output we can see that NULL is different from 0 and nullptr. So, develop the habit of using
nullptr directly.
In addition, in the above code, we used decltype and std::is_same which are modern C++ syntax.
14
2.1 Constants CHAPTER 02: LANGUAGE USABILITY ENHANCEMENTS
In simple terms, decltype is used for type derivation, and std::is_same is used. To compare the equality
of the two types, we will discuss them in detail later in the decltype section.
constexpr
C++ itself already has the concept of constant expressions, such as 1+2, 3*4. Such expressions
always produce the same result without any side effects. If the compiler can directly optimize and embed
these expressions into the program at compile time, it will increase the performance of the program. A
very obvious example is in the definition phase of an array:
4 int len_foo () {
5 int i = 2;
6 return i;
7 }
8 constexpr int len_foo_constexpr () {
9 return 5;
10 }
11
16
17 int main () {
18 char arr_1 [10]; // legal
19 char arr_2 [LEN ]; // legal
20
15