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.
C++ programmers, who are still using **traditional C++** (this book refers to C++98 and its previous C++ standards as traditional C++), may even amazed 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.
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.
> **Note**: Deprecation is not completely unusable, it is only intended to imply that features 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.
-**The string literal constant is no longer allowed to be assigned to a `char *`. If you need to assign and initialize a `char *` with a string literal constant, you should use `const char *` or `auto`.**
```cpp
char *str = "hello world!"; // A deprecation warning will appear
Lambda expressions are one of the most important features in modern C++, and Lambda expressions actually provide a feature like anonymous functions.
Anonymous functions are used when a function is needed, but you don't want to use a function to name a function. There are actually many, many scenes like this.
Anonymous functions are used when a function is needed, but you don’t want to use name to call a function. There are actually many, many scenes like this.
So anonymous functions are almost standard on modern programming languages.
###Basics
@@ -24,7 +24,7 @@ The basic syntax of a Lambda expression is as follows:
}
```
The above grammar rules are well understood except for the things in `[catch list]`,
The above grammar rules are well understood except for the things in `[capture list]`,
except that the function name of the general function is omitted.
The return value is in the form of a `->`
(we have already mentioned this in the tail return type earlier in the previous section).
@@ -143,7 +143,7 @@ void lambda_generic() {
##3.2 Function Object Wrapper
Although this part of the standard library is part of the standard library,
Although the features are part of the standard library and not found in runtime,
it enhances the runtime capabilities of the C++ language.
This part of the content is also very important, so put it here for introduction.
@@ -262,7 +262,7 @@ are all pure rvalue values.
**xvalue, expiring value** is the concept proposed by C++11 to introduce
rvalue references (so in traditional C++, pure rvalue and rvalue are the same concept),
that is, A value that is destroyed but can be moved.
a value that is destroyed but can be moved.
It would be a little hard to understand the xvalue,
@@ -26,7 +26,7 @@ These smart pointers include `std::shared_ptr`/`std::unique_ptr`/`std::weak_ptr`
##5.2 `std::shared_ptr`
`std::shared_ptr` is a smart pointer that records how many `shared_ptr` points to an object, eliminating the display call `delete`, which automatically deletes the object when the reference count becomes zero.
`std::shared_ptr` is a smart pointer that records how many `shared_ptr` points to an object, eliminating to call `delete`, which automatically deletes the object when the reference count becomes zero.
But not enough, because using `std::shared_ptr` still needs to be called with `new`, which makes the code a certain degree of asymmetry.
@@ -133,12 +133,12 @@ int main() {
// p2 is empty, no prints
if(p2) p2->foo();
std::cout << "p2 was destroied" << std::endl;
std::cout << "p2 was destroyed" << std::endl;
}
// p1 is not empty, prints
if (p1) p1->foo();
// Foo instance will be destroied when leaving the scope
// Foo instance will be destroyed when leaving the scope
}
```
@@ -157,14 +157,14 @@ class A {
public:
std::shared_ptr<B> pointer;
~A() {
std::cout << "A was destroied" << std::endl;
std::cout << "A was destroyed" << std::endl;
}
};
classB {
public:
std::shared_ptr<A> pointer;
~B() {
std::cout << "B was destroied" << std::endl;
std::cout << "B was destroyed" << std::endl;
}
};
intmain() {
@@ -177,9 +177,9 @@ int main() {
}
```
The result is that A and B will not be destroyed. This is because the pointer inside a, b also references `a, b`, which makes the reference count of `a, b` become 2, leaving the scope. When the `a, b` smart pointer is destructed, it can only cause the reference count of this area to be decremented by one. This causes the memory area reference count pointed to by the `a, b` object to be non-zero, but the external has no The way to find this area, it also caused a memory leak, as shown in Figure 5.1:
The result is that A and B will not be destroyed. This is because the pointer inside a, b also references `a, b`, which makes the reference count of `a, b` become 2, leaving the scope. When the `a, b` smart pointer is destructed, it can only cause the reference count of this area to be decremented by one. This causes the memory area reference count pointed to by the `a, b` object to be non-zero, but the external has no way to find this area, it also caused a memory leak, as shown in Figure 5.1:
The solution to this problem is to use the weak reference pointer `std::weak_ptr`, which is a weak reference (compared to `std::shared_ptr` is a strong reference). A weak reference does not cause an increase in the reference count. When a weak reference is used, the final release process is shown in Figure 5.2:
@@ -35,9 +35,9 @@ C++11 introduces a class related to `mutex`, with all related functions in the `
It can be locked by its member function `lock()`, and `unlock()` can be unlocked.
But in the process of actually writing the code, it is best not to directly call the member function,
Because calling member functions, you need to call `unlock()` at the exit of each critical section, and of course, exceptions.
At this time, C++11 also provides a template class `std::lock_gurad` for the RAII syntax for the mutex.
At this time, C++11 also provides a template class `std::lock_guard` for the RAII syntax for the mutex.
RAII guarantees the exceptional security of the code while losing the simplicity of the code.
RAII guarantees the exceptional security of the code while keeping the simplicity of the code.
```cpp
#include<iostream>
@@ -156,7 +156,7 @@ The condition variable `std::condition_variable` was born to solve the deadlock
For example, a thread may need to wait for a condition to be true to continue execution.
A dead wait loop can cause all other threads to fail to enter the critical section so that when the condition is true, a deadlock occurs.
Therefore, the `condition_variable` instance is created primarily to wake up the waiting thread and avoid deadlocks.
`notd_one()` of `std::condition_variable` is used to wake up a thread;
`notify_one()` of `std::condition_variable` is used to wake up a thread;
`notify_all()` is to notify all threads. Below is an example of a producer and consumer model:
```cpp
@@ -253,7 +253,7 @@ int main() {
}
```
Intuitively, ʻa = 5;` in `t2` seems to always execute before `flag = 1;`, and `while (flag != 1)` in `t1` seems to guarantee `std ::cout << "b = " << b << std::endl;` will not be executed before the mark is changed. Logically, it seems that the value of `b` should be equal to 5.
Intuitively, `a = 5;` seems in `t2` seems to always execute before `flag = 1;`, and `while (flag != 1)` in `t1` seems to guarantee `std ::cout << "b = " << b << std::endl;` will not be executed before the mark is changed. Logically, it seems that the value of `b` should be equal to 5.
But the actual situation is much more complicated than this, or the code itself is undefined behavior, because for `a` and `flag`, they are read and written in two parallel threads.
There has been competition. In addition, even if we ignore competing reading and writing, it is still possible to receive out-of-order execution of the CPU, and the impact of the compiler on the rearrangement of instructions.
Cause `a = 5` to occur after `flag = 1`. Thus `b` may output 0.
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.
We use optional third-party analytics cookies to understand how you use GitHub.com so we can build better products.
Learn more.
We use optional third-party analytics cookies to understand how you use GitHub.com so we can build better products.
You can always update your selection by clicking Cookie Preferences at the bottom of the page.
For more information, see our Privacy Statement.
Essential cookies
We use essential cookies to perform essential website functions, e.g. they're used to log you in.
Learn more
Always active
Analytics cookies
We use analytics cookies to understand how you use our websites so we can make them better, e.g. they're used to gather information about the pages you visit and how many clicks you need to accomplish a task.
Learn more