commit
ac4cd9366d
357
README.md
357
README.md
@ -1,151 +1,124 @@
|
||||
# C++ 那些事
|
||||
# Stories About C Plus Plus
|
||||
|
||||
Thanks for all the support about << Stories About C ++ >>, right now you could open this link(https://light-city.club/sc/) to read this article.
|
||||
Any star, retweet or pr will be weclomed.
|
||||
|
||||
|
||||
感谢各位对《C++ 那些事》的支持,现将内容也同步至网站,可以打开网站直接阅读~欢迎大家 star、转发、PR。
|
||||
|
||||
[直通点](https://light-city.club/sc/)
|
||||
|
||||
https://light-city.club/sc/
|
||||
-----------------------
|
||||
|
||||
|
||||
### 关于作者
|
||||
### 0. Directory
|
||||
|
||||
公众号已开放两大入口,分别是专辑与菜单,可以直接在微信公众号上阅读《C++那些事》内容,配上该仓库的代码,将会非常的爽,建议大家关注一波。
|
||||
- Chinese version:**C++ 那些事**
|
||||
- English version:**Stories About C Plus Plus**
|
||||
|
||||
个人公众号:guangcity
|
||||
This repository meets the need of people who wants to really know about C++, and may help you in the interview. Besides, it also provides
|
||||
other details,such as in-depth source code analysis and multi-threaded concurrency. It is a comprehensive C ++ repository from entry to advanced improvement
|
||||
|
||||

|
||||
### 1.Foundation
|
||||
|
||||
欢迎大家反馈及C++交流,本人在微信创建了C++那些事交流群,优质的C++资源交流区,期待大家关注上面公众号,点击公众号右下角->联系我,拉你入群。
|
||||
- [Stories About const](./basic_content/const)
|
||||
- [Stories About static](./basic_content/static)
|
||||
- [Stories about this](./basic_content/this)
|
||||
- [Stories About inline](./basic_content/inline)
|
||||
- [Stories About sizeof](./basic_content/sizeof)
|
||||
- [Stories About pointer of function](./basic_content/func_pointer)
|
||||
- [Stories About pure virtual function and abstract](./basic_content/abstract)
|
||||
- [Stories About vptr_vtable](./basic_content/vptr_vtable)
|
||||
- [Stories About virtual](./basic_content/virtual)
|
||||
- [Stories About volatile](./basic_content/volatile)
|
||||
- [Stories About assert](./basic_content/assert)
|
||||
- [Stories About bit](./basic_content/bit)
|
||||
- [Stories About extern](./basic_content/extern)
|
||||
- [Stories About struct](./basic_content/struct)
|
||||
- [Stories About struct and class](./basic_content/struct_class)
|
||||
- [Stories About union](./basic_content/union)
|
||||
- [Stories About polymorphism](./basic_content/c_poly)
|
||||
- [Stories About explicit](./basic_content/explicit)
|
||||
- [Stories About friend](./basic_content/friend)
|
||||
- [Stories About using](./basic_content/using)
|
||||
- [Stories About :: ](./basic_content/maohao)
|
||||
- [Stories About enum](./basic_content/enum)
|
||||
- [Stories About decltype](./basic_content/decltype)
|
||||
- [Stories About pointer_refer](./basic_content/pointer_refer)
|
||||
- [Stories About macro](./basic_content/macro)
|
||||
|
||||
---
|
||||
### 2.Code Samples
|
||||
|
||||
#### 2.1 10 Days Practice
|
||||
|
||||
- [x] day1
|
||||
|
||||
### 项目运行
|
||||
Basic Grammar About C ++
|
||||
- [x] day2
|
||||
|
||||
- **代码环境**
|
||||
Recursive、Structor、Enumerate、Static Variable
|
||||
|
||||
Ubuntu 18.04
|
||||
- [x] day3
|
||||
|
||||
- **工具**
|
||||
Function
|
||||
|
||||
CLion gcc/g++
|
||||
- [x] day4
|
||||
|
||||
尽量用g++,因为一开始我用的vim写的,所以纯g++,后来用编译器CLion,部分有CMakeLists.txt文件,直接导入就行,后面会更新这个文件包含整个项目,持续关注~
|
||||
Thorough About Function
|
||||
|
||||
### 0.项目概要
|
||||
- [x] day5
|
||||
|
||||
- 中文名:**C++ 那些事**
|
||||
- 英文名:**Stories About C Plus Plus**
|
||||
Inheritance and Polymorphism
|
||||
|
||||
这是一个适合初学者从<u>**入门到进阶**</u>的仓库,解决了<u>**面试者与学习者**</u>想要<u>**深入 C++**</u>及如何<u>**入坑 C++**</u>的问题。除此之外,本仓库拓展了更加深入的源码分析,多线程并发等的知识,是一个比较全面的 C++ 学习从入门到进阶提升的仓库。
|
||||
- [x] day6
|
||||
|
||||
### 1.基础进阶
|
||||
Vitrual Function、Abstruct
|
||||
|
||||
- [const 那些事](./basic_content/const)
|
||||
- [static 那些事](./basic_content/static)
|
||||
- [this 那些事](./basic_content/this)
|
||||
- [inline 那些事](./basic_content/inline)
|
||||
- [sizeof 那些事](./basic_content/sizeof)
|
||||
- [函数指针那些事](./basic_content/func_pointer)
|
||||
- [纯虚函数和抽象类那些事](./basic_content/abstract)
|
||||
- [vptr_vtable 那些事](./basic_content/vptr_vtable)
|
||||
- [virtual 那些事](./basic_content/virtual)
|
||||
- [volatile 那些事](./basic_content/volatile)
|
||||
- [assert 那些事](./basic_content/assert)
|
||||
- [位域那些事](./basic_content/bit)
|
||||
- [extern 那些事](./basic_content/extern)
|
||||
- [struct 那些事](./basic_content/struct)
|
||||
- [struct 与 class 那些事](./basic_content/struct_class)
|
||||
- [union 那些事](./basic_content/union)
|
||||
- [c 实现 c++ 多态那些事](./basic_content/c_poly)
|
||||
- [explicit 那些事](./basic_content/explicit)
|
||||
- [friend 那些事](./basic_content/friend)
|
||||
- [using 那些事](./basic_content/using)
|
||||
- [:: 那些事](./basic_content/maohao)
|
||||
- [enum 那些事](./basic_content/enum)
|
||||
- [decltype 那些事](./basic_content/decltype)
|
||||
- [引用与指针那些事](./basic_content/pointer_refer)
|
||||
- [宏那些事](./basic_content/macro)
|
||||
- [x] day7
|
||||
|
||||
### 2.实战系列
|
||||
Operator overloading
|
||||
|
||||
#### 2.1 [10日狂练](./practical_exercises/10_day_practice)
|
||||
- [x] day8
|
||||
|
||||
- [x] [day1](practical_exercises/10_day_practice/day1)
|
||||
Template And STL
|
||||
|
||||
基本c++语法
|
||||
- [x] day9
|
||||
|
||||
- [x] [day2](practical_exercises/10_day_practice/day2)
|
||||
Exception
|
||||
|
||||
递归、结构体、枚举、静态变量等
|
||||
- [x] day10
|
||||
|
||||
- [x] [day3](practical_exercises/10_day_practice/day3)
|
||||
File And Stream
|
||||
|
||||
函数
|
||||
#### 2.2 Practical Exercises
|
||||
|
||||
- [x] [day4](practical_exercises/10_day_practice/day4)
|
||||
├── [Square brackets overload .cpp](./practical_exercises/key_exercises/中括号重载.cpp)
|
||||
├── [Clock++operator overloading.cpp](./practical_exercises/key_exercises/时钟++运算符重载.cpp)
|
||||
├── [Mandatory conversion of operator overloading.cpp](./practical_exercises/key_exercises/运算符重载之强制转换.cpp)
|
||||
└── [Clock with overloaded parenthesis.cpp](./practical_exercises/key_exercises/重载圆括号的时钟.cpp)
|
||||
|
||||
函数深入
|
||||
├── [Template of Function.cpp](./practical_exercises/key_exercises/函数模板.cpp)
|
||||
|
||||
- [x] [day5](practical_exercises/10_day_practice/day5)
|
||||
├── [Dynamic array.cpp](./practical_exercises/key_exercises/动态数组.cpp)
|
||||
|
||||
继承多态
|
||||
├── [Dictionary insertion and search.cpp](./practical_exercises/key_exercises/字典插入与查找.cpp)
|
||||
|
||||
- [x] [day6](practical_exercises/10_day_practice/day6)
|
||||
├── [Catch Exception.cpp](./practical_exercises/key_exercises/异常捕获.cpp)
|
||||
|
||||
虚函数、抽象类
|
||||
├── [Template of Stack.cpp](./practical_exercises/key_exercises/类模板之栈.cpp)
|
||||
|
||||
- [x] [day7](practical_exercises/10_day_practice/day7)
|
||||
├── [Template of Array.cpp](./practical_exercises/key_exercises/类模板特化之数组.cpp)
|
||||
|
||||
运算符重载
|
||||
├── [Inheritance And Package.cpp](./practical_exercises/key_exercises/继承与封装.cpp)
|
||||
|
||||
- [x] [day8](practical_exercises/10_day_practice/day8)
|
||||
├── [Read And Write files.cpp](./practical_exercises/key_exercises/读写文件综合题.cpp)
|
||||
├── [Operator Overloading About Input and Output.cpp](./practical_exercises/key_exercises/输入输出运算符重载.cpp)
|
||||
├── [Input And Output Overloading.cpp](./practical_exercises/key_exercises/输入输出重载.cpp)
|
||||
├── [Input Format.cpp](./practical_exercises/key_exercises/输出格式.cpp)
|
||||
|
||||
模板与STL
|
||||
### 2.[C++2.0 New Features](./c++2.0)
|
||||
|
||||
- [x] [day9](practical_exercises/10_day_practice/day9)
|
||||
#### 2.0 Overview
|
||||
|
||||
异常
|
||||
C++2.0 is an Abbreviation, meaning「modern C++」,including C++11/14/17/20.
|
||||
|
||||
- [x] [day10](practical_exercises/10_day_practice/day10)
|
||||
|
||||
文件与流
|
||||
|
||||
#### 2.2 [重点实战练习](./practical_exercises/key_exercises/)
|
||||
|
||||
├── [中括号重载.cpp](./practical_exercises/key_exercises/中括号重载.cpp)
|
||||
├── [时钟++运算符重载.cpp](./practical_exercises/key_exercises/时钟++运算符重载.cpp)
|
||||
├── [运算符重载之强制转换.cpp](./practical_exercises/key_exercises/运算符重载之强制转换.cpp)
|
||||
└── [重载圆括号的时钟.cpp](./practical_exercises/key_exercises/重载圆括号的时钟.cpp)
|
||||
|
||||
├── [函数模板.cpp](./practical_exercises/key_exercises/函数模板.cpp)
|
||||
|
||||
├── [动态数组.cpp](./practical_exercises/key_exercises/动态数组.cpp)
|
||||
|
||||
├── [字典插入与查找.cpp](./practical_exercises/key_exercises/字典插入与查找.cpp)
|
||||
|
||||
├── [异常捕获.cpp](./practical_exercises/key_exercises/异常捕获.cpp)
|
||||
|
||||
├── [类模板之栈.cpp](./practical_exercises/key_exercises/类模板之栈.cpp)
|
||||
|
||||
├── [类模板特化之数组.cpp](./practical_exercises/key_exercises/类模板特化之数组.cpp)
|
||||
|
||||
├── [继承与封装.cpp](./practical_exercises/key_exercises/继承与封装.cpp)
|
||||
|
||||
├── [读写文件综合题.cpp](./practical_exercises/key_exercises/读写文件综合题.cpp)
|
||||
├── [输入输出运算符重载.cpp](./practical_exercises/key_exercises/输入输出运算符重载.cpp)
|
||||
├── [输入输出重载.cpp](./practical_exercises/key_exercises/输入输出重载.cpp)
|
||||
├── [输出格式.cpp](./practical_exercises/key_exercises/输出格式.cpp)
|
||||
|
||||
### 3.[C++2.0 新特性](./c++2.0)
|
||||
|
||||
#### 3.0 概况
|
||||
|
||||
C++2.0 是一个简称,意为「现代 C++」,包括 C++11/14/17/20。
|
||||
|
||||
#### 3.1 [C++11 新特性](./c++2.0/c++11)
|
||||
#### 2.1 [C++11 New Features](./c++2.0/c++11)
|
||||
|
||||
- [Variadic Templates](./c++2.0/variadic)
|
||||
|
||||
@ -153,7 +126,7 @@ C++2.0 是一个简称,意为「现代 C++」,包括 C++11/14/17/20。
|
||||
|
||||
```cpp
|
||||
vector<list<int> > //ok in each C++ version
|
||||
vector<list<int>> // before c++ 11 error error: ‘>>’ should be ‘> >’ within a nested template argument list,c++11后可以正常通过
|
||||
vector<list<int>> // before c++ 11 error error: ‘>>’ should be ‘> >’ within a nested template argument list,version beyond c++ 11 could compile successfully
|
||||
```
|
||||
|
||||
- [nullptr and nullptr_t](./c++2.0/nullptr.cpp)
|
||||
@ -176,8 +149,8 @@ C++2.0 是一个简称,意为「现代 C++」,包括 C++11/14/17/20。
|
||||
|
||||
- [=default,=delete](./c++2.0/default_delete.cpp)
|
||||
|
||||
如果你自行定义了一个 ctor,那么编译器就不会给你一个 default ctor
|
||||
如果强制加上 =default,就可以重新获得并使用 default ctor.
|
||||
If you define a ctor by yourself, compiler won't compile the default ctor.
|
||||
If you add =default, you could recatch and use default ctor.
|
||||
|
||||
- Alias(化名)Template(template typedef)
|
||||
|
||||
@ -202,30 +175,29 @@ C++2.0 是一个简称,意为「现代 C++」,包括 C++11/14/17/20。
|
||||
|
||||
- [move aware class](./c++2.0/move.cpp)
|
||||
|
||||
- 容器-结构与分类
|
||||
- Container-Struct And Classify
|
||||
|
||||
- (1) 序列式容器包括:`array`(C++2.0 新引入),`vector`,`deque`,`list`,`forward_list`(C++2.0 新引入)
|
||||
- (2) 关联式容器包括:`set/multiset`,`map/multimap`
|
||||
- (3) 无序容器(C++2.0 新引入,更换原先 `hash_xxx` 为 `unordered_xxx`)包括:`unordered_map/unordered_multimap,unordered_set/unordered_multiset`
|
||||
- (1) Serial containers include:`array`(C++2.0 Newly Introduced),`vector`,`deque`,`list`,`forward_list`(C++2.0 Newly Introduced)
|
||||
- (2) Associated containers include:`set/multiset`,`map/multimap`
|
||||
- (3) Unordered container(C++2.0 Newly Introduced,replace `hash_xxx` to `unordered_xxx`) include:`unordered_map/unordered_multimap,unordered_set/unordered_multiset`
|
||||
|
||||
- [Hash Function](./c++2.0/hash.cpp)
|
||||
|
||||
- [tuple](./c++2.0/tuple.cpp)
|
||||
|
||||
学习资料:https://www.bilibili.com/video/av51863195?from=search&seid=3610634846288253061
|
||||
Learning Material:https://www.bilibili.com/video/av51863195?from=search&seid=3610634846288253061
|
||||
|
||||
#### 3.2 C++14/17/20
|
||||
### 2.2 C++14/17/20
|
||||
|
||||
待更新...
|
||||
To Be Continued ...
|
||||
|
||||
### 4.设计模式
|
||||
### 3.Design Pattern
|
||||
|
||||
- [单例模式](./design_pattern/singleton)
|
||||
- [生产消费者模式](./design_pattern/producer_consumer)
|
||||
- [Singleton pattern](./design_pattern/singleton)
|
||||
|
||||
### 5. [STL 源码剖析](./src_analysis/stl)
|
||||
### 4. [STL Source Code Analysis](./src_analysis/stl)
|
||||
|
||||
**STL 源码剖析:gcc 4.9.1**
|
||||
**STL Source Code Analysis:gcc 4.9.1**
|
||||
|
||||
- [array](./src_analysis/stl/array.md)
|
||||
- [deque](./src_analysis/stl/deque.md)
|
||||
@ -235,83 +207,83 @@ C++2.0 是一个简称,意为「现代 C++」,包括 C++11/14/17/20。
|
||||
- [typename](./src_analysis/stl/typename.md)
|
||||
- [traits](./src_analysis/stl/traits.md)
|
||||
- [iterator](./src_analysis/stl/iterator.md)
|
||||
- [谈谈 STL 设计之 EBO 优化](./src_analysis/stl/谈谈STL设计之EBO优化.md)
|
||||
- [Talking about STL design and EBO optimization](./src_analysis/stl/谈谈STL设计之EBO优化.md)
|
||||
- [rb_tree](./src_analysis/stl/rb_tree.md)
|
||||
- [set and multiset](set_multiset.md)
|
||||
- [map and multimap](./src_analysis/stl/map_multimap.md)
|
||||
- [hashtable](./src_analysis/stl/hashtable.md)
|
||||
- [myhashtable](./src_analysis/stl/myhashtable.md)
|
||||
- [myhashtable](./src_analysis/stl/myPhashtable.md)
|
||||
- [unordered_map](./src_analysis/stl/unordered_map.md)
|
||||
|
||||
### 6. [并发编程](./concurrency)
|
||||
### 4. [Concurrent Programming](./concurrency)
|
||||
|
||||
#### 6.1 C++ Concurrency in Action
|
||||
#### 4.1 C++ Concurrency in Action
|
||||
|
||||
- [第一章](./concurrency/concurrency_v1/chapter1)
|
||||
- [第二章](./concurrency/concurrency_v1/chapter2)
|
||||
- [Chapter One](./concurrency/concurrency_v1/chapter1)
|
||||
- [Chapter Two](./concurrency/concurrency_v1/chapter2)
|
||||
|
||||
学习资料:https://chenxiaowei.gitbook.io/cpp_concurrency_in_action/
|
||||
Learning materials: https://chenxiaowei.gitbook.io/cpp_concurrency_in_action/
|
||||
|
||||
#### 6.2 多线程与多进程
|
||||
#### 4.2 Multithreading And Multiprocess
|
||||
|
||||
##### 6.2.1 Threading In C++
|
||||
##### 4.2.1 Threading In C++
|
||||
|
||||
- [介绍](./concurrency/Threading_In_CPlusPlus/1.thread)
|
||||
- [创建线程的五种类型](./concurrency/Threading_In_CPlusPlus/2.create_type)
|
||||
- [Join 与 Detachs](./concurrency/Threading_In_CPlusPlus/3.join_detach)
|
||||
- [Introduction](./concurrency/Threading_In_CPlusPlus/1.thread)
|
||||
- [Five Types of Thread Creation](./concurrency/Threading_In_CPlusPlus/2.create_type)
|
||||
- [Join And Detachs](./concurrency/Threading_In_CPlusPlus/3.join_detach)
|
||||
- [mutex in C++ Threading](./concurrency/Threading_In_CPlusPlus/4.mutex)
|
||||
|
||||
> 学习自:
|
||||
> From:
|
||||
>
|
||||
> https://www.youtube.com/watch?v=eZ8yKZo-PGw&list=PLk6CEY9XxSIAeK-EAh3hB4fgNvYkYmghp&index=4
|
||||
|
||||
### 7. [C++ 惯用法](./codingStyleIdioms)
|
||||
### 5. [C++ Conventional method](./codingStyleIdioms)
|
||||
|
||||
##### 你最喜欢的 c++ 编程风格惯用法是什么?
|
||||
##### What is your favorite custom for c ++ programming style?
|
||||
|
||||
- [1.类初始化列表](./codingStyleIdioms/1_classInitializers)
|
||||
- [2.枚举类替换命名空间](./codingStyleIdioms/2_enumclass_namespace)
|
||||
- [3.RAII(资源获取即初始化)](./codingStyleIdioms/3_RAII)
|
||||
- [4.copy and swap](./codingStyleIdioms/4_copy-swap)
|
||||
- [5.pImpl(指针指向具体实现)](./codingStyleIdioms/5_pImpl)
|
||||
- [1.ClassInitializers](./codingStyleIdioms/1_classInitializers)
|
||||
- [2.Replace Enumclass with Namespace](./codingStyleIdioms/2_enumclass_namespace)
|
||||
- [3.RAII(Resource Acquisition Initialization)](./codingStyleIdioms/3_RAII)
|
||||
- [4.Copy and Swap](./codingStyleIdioms/4_copy-swap)
|
||||
- [5.pImpl(Pointer Implement)](./codingStyleIdioms/5_pImpl)
|
||||
|
||||
### 8.学习课程
|
||||
### 6.Learning Courses
|
||||
|
||||
#### 8.1 [极客时间《现代 C++ 实战 30 讲》](https://time.geekbang.org/channel/home)
|
||||
#### 6.1 [Chinese Name:极客时间《现代 C++ 实战 30 讲》](https://time.geekbang.org/channel/home)
|
||||
|
||||
- [堆、栈、RAII:C++ 里该如何管理资源?](./learn_class/modern_C++_30/RAII)
|
||||
- [堆](./modern_++_30/RAII/heap.cpp)
|
||||
- [栈](./learn_class/modern_C++_30/RAII/stack.cpp)
|
||||
- [heap、stack、RAII:How to manage resources for C ++ ?](./learn_class/modern_C++_30/RAII)
|
||||
- [heap](./modern_++_30/RAII/heap.cpp)
|
||||
- [stack](./learn_class/modern_C++_30/RAII/stack.cpp)
|
||||
- [RAII](./learn_class/modern_C++_30/RAII/RAII.cpp)
|
||||
- [自己动手,实现 C++ 的智能指针](./learn_class/modern_C++_30/smart_ptr)
|
||||
- [Implementing smart pointers for C ++](./learn_class/modern_C++_30/smart_ptr)
|
||||
- [auto_ptr、scope_ptr](./learn_class/modern_C++_30/smart_ptr/auto_scope.cpp)
|
||||
- [unique_ptr](./learn_class/modern_C++_30/smart_ptr/unique_ptr.cpp)
|
||||
- [shared_ptr](./learn_class/modern_C++_30/smart_ptr/shared_ptr.cpp)
|
||||
- [右值和移动究竟解决了什么问题?](./learn_class/modern_C++_30/reference)
|
||||
- [左值与右值](./learn_class/modern_C++_30/reference/reference.cpp)
|
||||
- [延长声明周期](./learn_class/modern_C++_30/reference/lifetime.cpp)
|
||||
- [引用折叠](./learn_class/modern_C++_30/reference/collapses.cpp)
|
||||
- [完美转发](./learn_class/modern_C++_30/reference/forward.cpp)
|
||||
- [不要返回本地变量的引用](./learn_class/modern_C++_30/reference/don'treturnReference.cpp)
|
||||
- [容器 1](./learn_class/modern_C++_30/container1)
|
||||
- [容器 2](./learn_class/modern_C++_30/container2)
|
||||
- [异常](./learn_class/modern_C++_30/exception)
|
||||
- [字面量、静态断言和成员函数说明符](./learn_class/modern_C++_30/literalAssert)
|
||||
- [是不是应该返回对象?](./learn_class/modern_C++_30/returnObj)
|
||||
- [编译期多态:泛型编程和模板入门](./learn_class/modern_C++_30/compilerpoly)
|
||||
- [译期能做些什么?一个完整的计算世界](./learn_class/modern_C++_30/compilercompute)
|
||||
- [SFINAE:不是错误的替换失败是怎么回事?](./learn_class/modern_C++_30/SFINAE)
|
||||
- [constexpr:一个常态的世界](./learn_class/modern_C++_30/constexpr)
|
||||
- [函数对象和 lambda:进入函数式编程](./learn_class/modern_C++_30/functionLambda)
|
||||
- [内存模型和 atomic:理解并发的复杂性](./learn_class/modern_C++_30/memorymodel_atomic)
|
||||
- [What exactly does r value and move solve?](./learn_class/modern_C++_30/reference)
|
||||
- [L value and R value](./learn_class/modern_C++_30/reference/reference.cpp)
|
||||
- [Extend the declaration cycle](./learn_class/modern_C++_30/reference/lifetime.cpp)
|
||||
- [Reference folding](./learn_class/modern_C++_30/reference/collapses.cpp)
|
||||
- [Perfect forward](./learn_class/modern_C++_30/reference/forward.cpp)
|
||||
- [Do not return Reference](./learn_class/modern_C++_30/reference/don'treturnReference.cpp)
|
||||
- [Container 1](./learn_class/modern_C++_30/container1)
|
||||
- [Container 2](./learn_class/modern_C++_30/container2)
|
||||
- [Exception](./learn_class/modern_C++_30/exception)
|
||||
- [Literal、Static Assertion And Member Function Specifier](./learn_class/modern_C++_30/literalAssert)
|
||||
- [Return Object?](./learn_class/modern_C++_30/returnObj)c
|
||||
- [Getting started with generic programming and templates](./learn_class/modern_C++_30/compilerpoly)
|
||||
- [A whole Compiler Compute World](./learn_class/modern_C++_30/compilercompute)
|
||||
- [SFINAE:What is it if it is not replace error?](./learn_class/modern_C++_30/SFINAE)
|
||||
- [constexpr:A Normal World](./learn_class/modern_C++_30/constexpr)
|
||||
- [Function object and Lambda:functionLambda](./learn_class/modern_C++_30/functionLambda)
|
||||
- [Memory Model and Atomic:Understangding the complexity of concurrency](./learn_class/modern_C++_30/memorymodel_atomic)
|
||||
|
||||
### 9.工具篇
|
||||
### 7.Tools
|
||||
|
||||
#### 9.1 [容器快捷输出工具](./tool/output)
|
||||
#### 7.1 [Container shortcut output tool](./tool/output)
|
||||
|
||||
对吴老师的代码进行了修改,[点击此处直通代码](./tool/output/output_container.h)
|
||||
Modified the code, [Click here for the code](./tool/output/output_container.h)
|
||||
|
||||
输入:
|
||||
Input:
|
||||
|
||||
```cpp
|
||||
map<int, int> mp{
|
||||
@ -321,31 +293,42 @@ map<int, int> mp{
|
||||
cout << mp << endl;
|
||||
```
|
||||
|
||||
输出结果显示:
|
||||
Output:
|
||||
|
||||
```cpp
|
||||
{ 1 => 1, 2 => 4, 3 => 9 }
|
||||
```
|
||||
|
||||
#### 9.2 像 Python 一样简单输出(Jupyter Notebook)
|
||||
#### 7.2 Output Like Python(Jupyter Notebook)
|
||||
|
||||
- [像 Python 一样玩 C/C++](./tool/像Python一样玩CC++.md)
|
||||
- [How to output like python in C/C++](./tool/像Python一样玩CC++.md)
|
||||
|
||||
#### 9.3 观察编译过程变化
|
||||
#### 7.3 Observe the changes in the compilation process
|
||||
|
||||
- [https://cppinsights.io](https://cppinsights.io/)
|
||||
|
||||
#### 9.4 C++ 的 Debug 工具 dbg-macro
|
||||
#### 7.4 Debug Tools For C ++:dbg-macro
|
||||
|
||||
- [C++ 的 Debug 工具 dbg-macro](./tool/C++的Debug工具dbg-macro.md)
|
||||
- [Debug Tool: dbg-macro](./tool/C++的Debug工具dbg-macro.md)
|
||||
|
||||
### 10.拓展部分
|
||||
### 8.Expansion
|
||||
|
||||
#### 10.1 一些问题
|
||||
#### 8.1 Other Problems
|
||||
- [How to convert string to in C ++?](./extension/some_problem/string_int.md)
|
||||
|
||||
- [C++ 中如何将 string 类型转换为 int 类型?](./extension/some_problem/string_int.md)
|
||||
|
||||
### 11.贡献者
|
||||
### 9.Circumstance
|
||||
|
||||
|
||||
- **Running Circumstance**
|
||||
|
||||
Ubuntu 18.04
|
||||
|
||||
- **IDE**
|
||||
|
||||
CLion gcc/g++
|
||||
|
||||
### 10.Contributor
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
@ -366,22 +349,8 @@ map<int, int> mp{
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### 12.赞助我
|
||||
### 11.About The Writer
|
||||
|
||||
如果觉得不错,赞助我吧~
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th align="center" style="height=200 width="200">
|
||||
<img src="https://light-city.club/sc/assets/images/alipay.jpg" height="200" width="200" ><br>
|
||||
支付宝
|
||||
</th>
|
||||
<th align="center" style="height=200 width="200">
|
||||
<img src="https://light-city.club/sc/assets/images/wechat.png" height="200" width="200" ><br>
|
||||
微信
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
个人公众号:
|
||||
|
||||

|
||||
|
142
english/basic_content/abstract/README.md
Normal file
142
english/basic_content/abstract/README.md
Normal file
@ -0,0 +1,142 @@
|
||||
# Pure virtual functions and abstract classes
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
## 1.Pure virtual function and abstract class
|
||||
|
||||
|
||||
Pure virtual functions (or abstract functions) in C + + are virtual functions that we have not implemented!We just need to state it!
|
||||
example:
|
||||
```cpp
|
||||
// abstract class
|
||||
Class A {
|
||||
public:
|
||||
virtual void show() = 0; // pure virtual function
|
||||
/* Other members */
|
||||
};
|
||||
```
|
||||
|
||||
* Pure virtual function: virtual function without function body
|
||||
* Abstract classes: classes containing pure virtual functions
|
||||
|
||||
Abstract classes can only be used as base classes to derive new classes. Objects, pointers and references of abstract classes cannot be created->An object of a class derived from an abstract class!
|
||||
|
||||
> Code example:[test.cpp](./test.cpp)、[pure_virtual.cpp](./pure_virtual.cpp)
|
||||
|
||||
## 2.Implement abstract classes
|
||||
|
||||
Abstract class:Pure virtual functions can be called within member functions.Pure virtual functions cannot be used inside constructors / destructors.
|
||||
|
||||
If a class derives from an abstract class, it must implement all pure virtual functions in the base class to become a non abstract class.
|
||||
```cpp
|
||||
// A is abstract class
|
||||
class A {
|
||||
public:
|
||||
virtual void f() = 0; // pure virtual function
|
||||
void g(){ this->f(); }
|
||||
A(){} // 构造函数
|
||||
};
|
||||
|
||||
class B : public A{
|
||||
public:
|
||||
void f(){ cout<<"B:f()"<<endl;} // 实现了抽象类的纯虚函数
|
||||
};
|
||||
```
|
||||
|
||||
> Code Example:[abstract.cpp](./abstract.cpp)
|
||||
|
||||
## 3.Key point
|
||||
|
||||
- [Pure virtual functions make a class abstract](./interesting_facts1.cpp)
|
||||
```cpp
|
||||
// Abstract class contains at least one pure virtual function
|
||||
class Base{
|
||||
public:
|
||||
virtual void show() = 0; // 纯虚函数
|
||||
int getX() { return x; } // 普通成员函数
|
||||
|
||||
private:
|
||||
int x;
|
||||
};
|
||||
```
|
||||
|
||||
- [Pointers and references to abstract class types](./interesting_facts2.cpp)
|
||||
```cpp
|
||||
class Derived : public Base {
|
||||
public:
|
||||
void show() { cout << "In Derived \n"; } // 实现抽象类的纯虚函数
|
||||
Derived(){} // 构造函数
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
//Base b; // error! 不能创建抽象类的对象
|
||||
//Base *b = new Base(); error!
|
||||
|
||||
Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象
|
||||
bp->show();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
- [If we do not override pure virtual functions in the derived class, the derived class will also become an abstract class](./interesting_facts3.cpp)
|
||||
```cpp
|
||||
// Derived为抽象类
|
||||
class Derived: public Base
|
||||
{
|
||||
public:
|
||||
// void show() {}
|
||||
};
|
||||
```
|
||||
|
||||
- [Abstract classes can have constructors](./interesting_facts4.cpp)
|
||||
```cpp
|
||||
// abstract class
|
||||
class Base {
|
||||
protected:
|
||||
int x;
|
||||
public:
|
||||
virtual void fun() = 0;
|
||||
Base(int i) { x = i; } // constructor function
|
||||
};
|
||||
// 派生类
|
||||
class Derived: public Base
|
||||
{
|
||||
int y;
|
||||
public:
|
||||
Derived(int i, int j) : Base(i) { y = j; } // constructor function
|
||||
void fun() { cout << "x = " << x << ", y = " << y; }
|
||||
};
|
||||
```
|
||||
|
||||
- [A constructor cannot be a virtual function, and a destructor can be a virtual destructor](./interesting_facts5.cpp)
|
||||
```cpp
|
||||
// 抽象类
|
||||
class Base {
|
||||
public:
|
||||
Base(){ cout << "Constructor: Base" << endl; }
|
||||
virtual ~Base(){ cout << "Destructor : Base" << endl; }
|
||||
|
||||
virtual void func() = 0;
|
||||
};
|
||||
|
||||
class Derived: public Base {
|
||||
public:
|
||||
Derived(){ cout << "Constructor: Derived" << endl; }
|
||||
~Derived(){ cout << "Destructor : Derived" << endl;}
|
||||
|
||||
void func(){cout << "In Derived.func()." << endl;}
|
||||
};
|
||||
```
|
||||
>When the base class pointer points to a derived class object and removes the object, we may want to call the appropriate destructor.
|
||||
>The destructor can only be called if it is not a virtual destructor.
|
||||
|
||||
## 4.Complete example
|
||||
|
||||
Abstract classes are inherited and implemented by derived classes!
|
||||
|
||||
> Code Example:[derived_full.cpp](./derived_full.cpp)
|
27
english/basic_content/abstract/abstract.cpp
Normal file
27
english/basic_content/abstract/abstract.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @file abstract.cpp
|
||||
* @brief 抽象类中:在成员函数内可以调用纯虚函数,在构造函数/析构函数内部不能使用纯虚函数
|
||||
* 如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽象类
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
class A {
|
||||
public:
|
||||
virtual void f() = 0; // 纯虚函数
|
||||
void g(){ this->f(); }
|
||||
A(){}
|
||||
};
|
||||
class B:public A{
|
||||
public:
|
||||
void f(){ cout<<"B:f()"<<endl;}
|
||||
};
|
||||
int main(){
|
||||
B b;
|
||||
b.g();
|
||||
return 0;
|
||||
}
|
32
english/basic_content/abstract/derived_full.cpp
Normal file
32
english/basic_content/abstract/derived_full.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file derived_full.cpp
|
||||
* @brief 完整示例!抽象类由派生类继承实现!
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
class Base
|
||||
{
|
||||
int x;
|
||||
public:
|
||||
virtual void fun() = 0;
|
||||
int getX() { return x; }
|
||||
};
|
||||
|
||||
class Derived: public Base
|
||||
{
|
||||
int y;
|
||||
public:
|
||||
void fun() { cout << "fun() called"; } // 实现了fun()函数
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Derived d;
|
||||
d.fun();
|
||||
return 0;
|
||||
}
|
28
english/basic_content/abstract/interesting_facts1.cpp
Normal file
28
english/basic_content/abstract/interesting_facts1.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @file interesting_facts1.cpp
|
||||
* @brief 纯虚函数使一个类变成抽象类
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* @brief 抽象类至少包含一个纯虚函数
|
||||
*/
|
||||
class Test
|
||||
{
|
||||
int x;
|
||||
public:
|
||||
virtual void show() = 0;
|
||||
int getX() { return x; }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Test t; //error! 不能创建抽象类的对象
|
||||
return 0;
|
||||
}
|
||||
|
38
english/basic_content/abstract/interesting_facts2.cpp
Normal file
38
english/basic_content/abstract/interesting_facts2.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file interesting_facts2.cpp
|
||||
* @brief 抽象类类型的指针和引用
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 抽象类至少包含一个纯虚函数
|
||||
*/
|
||||
class Base
|
||||
{
|
||||
int x;
|
||||
public:
|
||||
virtual void show() = 0;
|
||||
int getX() { return x; }
|
||||
|
||||
};
|
||||
class Derived: public Base
|
||||
{
|
||||
public:
|
||||
void show() { cout << "In Derived \n"; }
|
||||
Derived(){}
|
||||
};
|
||||
int main(void)
|
||||
{
|
||||
//Base b; //error! 不能创建抽象类的对象
|
||||
//Base *b = new Base(); error!
|
||||
Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象
|
||||
bp->show();
|
||||
return 0;
|
||||
}
|
||||
|
29
english/basic_content/abstract/interesting_facts3.cpp
Normal file
29
english/basic_content/abstract/interesting_facts3.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @file interesting_facts3.cpp
|
||||
* @brief 如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类。
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
class Base
|
||||
{
|
||||
int x;
|
||||
public:
|
||||
virtual void show() = 0;
|
||||
int getX() { return x; }
|
||||
};
|
||||
class Derived: public Base
|
||||
{
|
||||
public:
|
||||
// void show() { }
|
||||
};
|
||||
int main(void)
|
||||
{
|
||||
Derived d; //error! 派生类没有实现纯虚函数,那么派生类也会变为抽象类,不能创建抽象类的对象
|
||||
return 0;
|
||||
}
|
||||
|
35
english/basic_content/abstract/interesting_facts4.cpp
Normal file
35
english/basic_content/abstract/interesting_facts4.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file interesting_facts4.cpp
|
||||
* @brief 抽象类可以有构造函数
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
// An abstract class with constructor
|
||||
class Base
|
||||
{
|
||||
protected:
|
||||
int x;
|
||||
public:
|
||||
virtual void fun() = 0;
|
||||
Base(int i) { x = i; }
|
||||
};
|
||||
|
||||
class Derived: public Base
|
||||
{
|
||||
int y;
|
||||
public:
|
||||
Derived(int i, int j):Base(i) { y = j; }
|
||||
void fun() { cout << "x = " << x << ", y = " << y; }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Derived d(4, 5);
|
||||
d.fun();
|
||||
return 0;
|
||||
}
|
30
english/basic_content/abstract/interesting_facts5.cpp
Normal file
30
english/basic_content/abstract/interesting_facts5.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
/**
|
||||
* @file interesting_facts5.cpp
|
||||
* @brief 构造函数不能是虚函数,而析构函数可以是虚析构函数。
|
||||
* 例如:当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。如果析构函数不是虚拟的,则只能调用基类析构函数。
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
class Base {
|
||||
public:
|
||||
Base() { cout << "Constructor: Base" << endl; }
|
||||
virtual ~Base() { cout << "Destructor : Base" << endl; }
|
||||
};
|
||||
|
||||
class Derived: public Base {
|
||||
public:
|
||||
Derived() { cout << "Constructor: Derived" << endl; }
|
||||
~Derived() { cout << "Destructor : Derived" << endl; }
|
||||
};
|
||||
|
||||
int main() {
|
||||
Base *Var = new Derived();
|
||||
delete Var;
|
||||
return 0;
|
||||
}
|
||||
|
34
english/basic_content/abstract/pure_virtual.cpp
Normal file
34
english/basic_content/abstract/pure_virtual.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @file pure_virtual.cpp
|
||||
* @brief 纯虚函数:没有函数体的虚函数
|
||||
* 抽象类:包含纯虚函数的类
|
||||
*
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
|
||||
using namespace std;
|
||||
class A
|
||||
{
|
||||
private:
|
||||
int a;
|
||||
public:
|
||||
virtual void show()=0; // 纯虚函数
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
/*
|
||||
* 1. 抽象类只能作为基类来派生新类使用
|
||||
* 2. 抽象类的指针和引用->由抽象类派生出来的类的对象!
|
||||
*/
|
||||
A a; // error 抽象类,不能创建对象
|
||||
|
||||
A *a1; // ok 可以定义抽象类的指针
|
||||
|
||||
A *a2 = new A(); // error, A是抽象类,不能创建对象
|
||||
}
|
23
english/basic_content/abstract/test.cpp
Normal file
23
english/basic_content/abstract/test.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file test.cpp
|
||||
* @brief C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它!通过声明中赋值0来声明纯虚函数!
|
||||
* 纯虚函数:没有函数体的虚函数
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 抽象类
|
||||
*/
|
||||
class Test
|
||||
{
|
||||
// Data members of class
|
||||
public:
|
||||
// Pure Virtual Function
|
||||
virtual void show() = 0;
|
||||
|
||||
/* Other members */
|
||||
};
|
59
english/basic_content/assert/README.md
Normal file
59
english/basic_content/assert/README.md
Normal file
@ -0,0 +1,59 @@
|
||||
# Things about assert
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 1.First assertion case
|
||||
|
||||
assert,**is macro,rather than function**。
|
||||
|
||||
assert The prototype of a macro is defined in <assert.h>(C)、<cassert>(C++).If its condition returns an error,Program execution is terminated.
|
||||
|
||||
You can close assert by defining 'ndebug', **But it needs to be at the beginning of the source code,before include <assert.h>.**
|
||||
|
||||
```c
|
||||
void assert(int expression);
|
||||
```
|
||||
|
||||
> Code Example:[assert.c](./assert.c)
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 7;
|
||||
|
||||
/* Some big code in between and let's say x
|
||||
is accidentally changed to 9 */
|
||||
x = 9;
|
||||
|
||||
// Programmer assumes x to be 7 in rest of the code
|
||||
assert(x==7);
|
||||
|
||||
/* Rest of the code */
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Output:
|
||||
```c
|
||||
assert: assert.c:13: main: Assertion 'x==7' failed.
|
||||
```
|
||||
|
||||
## 2.Assertion and normal error handling
|
||||
|
||||
+ Assertions are mainly used to check for logically impossible situations.
|
||||
|
||||
>For example, they can be used to check the state that code expects before it starts to run, or after the run is complete. Unlike normal error handling, assertions are usually disabled at run time.
|
||||
|
||||
+ Ignore the assertion and add at the beginning of the code:
|
||||
```c++
|
||||
#define NDEBUG // Adding this line,then you do not need the assert
|
||||
```
|
||||
|
||||
> Code Example:[ignore_assert.c](./ignore_assert.c)
|
18
english/basic_content/assert/assert.c
Normal file
18
english/basic_content/assert/assert.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 7;
|
||||
|
||||
/* Some big code in between and let's say x
|
||||
* is accidentally changed to 9 */
|
||||
x = 9;
|
||||
|
||||
// Programmer assumes x to be 7 in rest of the code
|
||||
assert(x==7);
|
||||
|
||||
/* Rest of the code */
|
||||
|
||||
return 0;
|
||||
}
|
17
english/basic_content/assert/ignore_assert.c
Normal file
17
english/basic_content/assert/ignore_assert.c
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @file ignore_assert.c
|
||||
* @brief 忽略断言
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-25
|
||||
*/
|
||||
|
||||
# define NDEBUG // 忽略断言
|
||||
|
||||
#include<assert.h>
|
||||
|
||||
int main(){
|
||||
int x=7;
|
||||
assert(x==5);
|
||||
return 0;
|
||||
}
|
177
english/basic_content/bit/README.md
Normal file
177
english/basic_content/bit/README.md
Normal file
@ -0,0 +1,177 @@
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
## What is Bit field ?
|
||||
|
||||
“ Bit field is a kind of data structure.Data can be stored compactly in bits, And allows the programmer to operate on the bits of this structure. One of the advantages of this data structure is that it can save storage space in data units, which is particularly important when programs need thousands of data units. The second advantage is that bit segments can easily access part of the contents of an integer value, which can simplify the program source code. The disadvantage of this data structure is that bit segment implementation depends on specific machines and systems, and different results may be obtained in different platforms, which leads to the fact that bit segments are not portable in nature
|
||||
|
||||
- The layout of bit fields in memory is machine dependent
|
||||
- The type of bit field must be integer or enumeration type. The behavior of bit field in signed type depends on the implementation
|
||||
- The addressing operator (&) cannot be applied to a bit field, and no pointer can point to a bit field of a class
|
||||
|
||||
## Bit field usage
|
||||
|
||||
Bit fields usually use struct declarations, which set the name of each bit field member and determine its width:
|
||||
|
||||
```
|
||||
struct bit_field_name
|
||||
{
|
||||
type member_name : width;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Elements | Description |
|
||||
| -------------- | ------------------------------------------------------------ |
|
||||
| bit_field_name | Bit field structure name |
|
||||
| type | must be int、signed int or unsigned int type |
|
||||
| member_name | |
|
||||
| width | |
|
||||
|
||||
For example, declare the following bit field:
|
||||
|
||||
```
|
||||
struct _PRCODE
|
||||
{
|
||||
unsigned int code1: 2;
|
||||
unsigned int cdde2: 2;
|
||||
unsigned int code3: 8;
|
||||
};
|
||||
struct _PRCODE prcode;
|
||||
```
|
||||
|
||||
This definition makes' prcode 'contain two 2-bit fields and one 8-bit field. We can use the member operator of the structure to assign values to it
|
||||
|
||||
```
|
||||
prcode.code1 = 0;
|
||||
prcode.code2 = 3;
|
||||
procde.code3 = 102;
|
||||
```
|
||||
|
||||
When assigning a value, it should be noted that the size of the value should not exceed the capacity of the bit field member,For example prcode.code3 Is a bit domain member of 8 bits. Its capacity is 2^8 = 256,Assignment range should be [0,255]。
|
||||
|
||||
## Size and alignment of bit fields
|
||||
|
||||
### Size of bit field
|
||||
|
||||
For example, the following bit field:
|
||||
|
||||
```
|
||||
struct box
|
||||
{
|
||||
unsigned int a: 1;
|
||||
unsigned int : 3;
|
||||
unsigned int b: 4;
|
||||
};
|
||||
```
|
||||
There is an unnamed bit field in the middle of the bit field structure, which occupies 3 bits and only plays a filling role and has no practical significance. The padding makes the structure use 8 bits in total. But C language uses unsigned int as the basic unit of bit field,Even if the only member of a structure is a bit field of 1 bit, the size of the structure is the same as that of an unsigned int.In some systems, the unsigned int is 16 bits, and in x86 systems it is 32 bits.For the following articles, the default value of unsigned int is 32 bits.
|
||||
|
||||
### Alignment of bit fields
|
||||
|
||||
A bit field member is not allowed to cross the boundary of two unsigned ints. If the total number of bits declared by a member exceeds the size of an unsigned int, the editor will automatically shift the bit field members to align them according to the boundary of the unsigned int
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
struct stuff
|
||||
{
|
||||
unsigned int field1: 30;
|
||||
unsigned int field2: 4;
|
||||
unsigned int field3: 3;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
`field1` + `field2` = 34 Bits,beyond 32 Bits, Complier`field2` move to the next unsigned int unit. stuff.field1 and stuff.field2 will leave the 2 Bits space, stuff.field3 follow closely stuff.field2.The structure is now of size 2 * 32 = 64 Bits。
|
||||
|
||||
This hole can be filled with the unnamed bit field member mentioned earlier, or we can use an unnamed bit field member with a width of 0 to align the next field member with the next integer.
|
||||
For example:
|
||||
|
||||
```
|
||||
struct stuff
|
||||
{
|
||||
unsigned int field1: 30;
|
||||
unsigned int : 2;
|
||||
unsigned int field2: 4;
|
||||
unsigned int : 0;
|
||||
unsigned int field3: 3;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
Between stuff.field1 and stuff.field2 there is a 2 Bits space. Stuff.field3 will be stored in the next unsigned in. The size of this structure is 3 * 32 = 96 Bits。
|
||||
|
||||
Code:[learn.cpp](learn.cpp)
|
||||
|
||||
## Initialization of bit field and remapping of bit
|
||||
|
||||
### Initialization
|
||||
|
||||
|
||||
The initialization method of bit field is the same as that of ordinary structure. Here, two methods are listed as follows:
|
||||
|
||||
```
|
||||
struct stuff s1= {20,8,6};
|
||||
```
|
||||
|
||||
Or directly assign values to the bit field members:
|
||||
|
||||
```
|
||||
struct stuff s1;
|
||||
s1.field1 = 20;
|
||||
s1.field2 = 8;
|
||||
s1.field3 = 4;
|
||||
```
|
||||
|
||||
### Re-mapping of bit field
|
||||
|
||||
Declare a bit field with a size of 32 bits
|
||||
|
||||
```
|
||||
struct box {
|
||||
unsigned int ready: 2;
|
||||
unsigned int error: 2;
|
||||
unsigned int command: 4;
|
||||
unsigned int sector_no: 24;
|
||||
}b1;
|
||||
```
|
||||
|
||||
#### Zeroing bit field by remapping
|
||||
|
||||
```
|
||||
int* p = (int *) &b1; // 将 "位域结构体的地址" 映射至 "整形(int*) 的地址"
|
||||
*p = 0; // clear s1, set all members to zero
|
||||
```
|
||||
|
||||
#### The 32 bits bit field is remapped to the unsigned int type by union
|
||||
|
||||
Let's briefly introduce the alliance
|
||||
|
||||
> "Union" is a special class and a data structure of construction type.Many different data types can be defined in a "union". Any kind of data defined by the "union" can be loaded into a variable described as the "union" type. These data share the same memory to save space
|
||||
>
|
||||
> There are some similarities between "union" and "structure". But there are essential differences between them.In a structure, each member has its own memory space. The total length of a structure variable is the sum of the length of each member (except for empty structure, and boundary adjustment is not considered).In Union, members share a certain amount of memory space, and the length of a union variable is equal to the longest length of each member.It should be noted that the so-called sharing does not mean that multiple members are loaded into a joint variable at the same time, but that the joint variable can be assigned any member value, but only one value can be assigned at a time.
|
||||
|
||||
We can declare the following Union:
|
||||
|
||||
```
|
||||
union u_box {
|
||||
struct box st_box;
|
||||
unsigned int ui_box;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
In x86 system, unsigned int and box are 32 Bits, Through this combination, St_ Box and UI_ Box shares a piece of memory.Which bit in the specific bit field corresponds to which bit of the unsigned int depends on the compiler and hardware.Use union to return the bit field to zero. The code is as follows:
|
||||
|
||||
```
|
||||
union u_box u;
|
||||
u.ui_box = 0;
|
||||
```
|
||||
|
||||
> From:<http://www.yuan-ji.me/C-C-%E4%BD%8D%E5%9F%9F-Bit-fields-%E5%AD%A6%E4%B9%A0%E5%BF%83%E5%BE%97/>
|
19
english/basic_content/bit/learn.cpp
Normal file
19
english/basic_content/bit/learn.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include<iostream>
|
||||
|
||||
using namespace std;
|
||||
struct stuff
|
||||
{
|
||||
unsigned int field1: 30;
|
||||
unsigned int : 2;
|
||||
unsigned int field2: 4;
|
||||
unsigned int : 0;
|
||||
unsigned int field3: 3;
|
||||
};
|
||||
int main(){
|
||||
struct stuff s={1,3,5};
|
||||
cout<<s.field1<<endl;
|
||||
cout<<s.field2<<endl;
|
||||
cout<<s.field3<<endl;
|
||||
cout<<sizeof(s)<<endl;
|
||||
return 0;
|
||||
}
|
46
english/basic_content/c_poly/README.md
Normal file
46
english/basic_content/c_poly/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Object oriented features of C + + implemented by C
|
||||
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
## 1.C++
|
||||
|
||||
Polymorphism in C ++ :In C++, we usually maintain a virtual function table. According to the assignment compatibility rule, we know that the pointer or reference of the parent class can point to the child class object
|
||||
|
||||
|
||||
|
||||
If the pointer or reference of a parent class calls the virtual function of the parent class, the pointer of the parent class will look up its function address in its own virtual function table.If the pointer or reference of the parent object points to an object of a subclass, and the subclass has overridden the virtual function of the parent class, the pointer will call the overridden virtual function of the subclass.
|
||||
|
||||
Code Example:[c++_examp.cpp](./c++_examp.cpp)
|
||||
|
||||
|
||||
|
||||
## 2.C Implement
|
||||
|
||||
- Encapsulation
|
||||
|
||||
There is no concept of class class in C language. But with struct structure, we can use struct to simulate;
|
||||
|
||||
Encapsulating properties and methods into structures using function pointers.
|
||||
|
||||
|
||||
|
||||
- Inherit
|
||||
|
||||
Structure nesting
|
||||
|
||||
|
||||
- Polymorphic
|
||||
|
||||
Class and subclass methods have different function pointers
|
||||
|
||||
There is no member function in the structure of C language. How to realize the common function of parent structure and child structure? We can consider using function pointers to simulate. But there is a flaw in this approach:The function pointer between the parent and child does not point to the virtual function table maintained in C ++, but a piece of physical memory. If there are too many simulated functions, it will not be easy to maintain.
|
||||
|
||||
In order to simulate polymorphism, function pointer variables must be aligned(They are completely consistent in content and alignment of variables).Otherwise, the parent class pointer points to the child class object, and the operation crashes!
|
||||
|
||||
|
||||
|
||||
Code example :[c_examp.c](./c_examp.c)
|
BIN
english/basic_content/c_poly/c++_examp
Executable file
BIN
english/basic_content/c_poly/c++_examp
Executable file
Binary file not shown.
43
english/basic_content/c_poly/c++_examp.cpp
Normal file
43
english/basic_content/c_poly/c++_examp.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file c++_examp.cpp
|
||||
* @brief c++中的多态
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-08-06
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
class A
|
||||
{
|
||||
public:
|
||||
virtual void f()//Implement a virtual function
|
||||
{
|
||||
cout << "Base A::f() " << endl;
|
||||
}
|
||||
};
|
||||
|
||||
class B:public A // 必须为共有继承,否则后面调用不到,class默认为私有继承!
|
||||
{
|
||||
public:
|
||||
virtual void f()//Virtual function implementation, virtual keyword in subclass can not be appearence
|
||||
{
|
||||
cout << "Derived B::f() " << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
A a;//Base class object
|
||||
B b;//an object of derived type
|
||||
|
||||
A* pa = &a;//The parent class pointer points to the parent object
|
||||
pa->f();//Call the function of the parent class
|
||||
pa = &b; //The parent class pointer points to the subclass object, which is implemented in polymorphism
|
||||
|
||||
|
||||
pa->f();//Call the function with the same name of the derived class
|
||||
return 0;
|
||||
}
|
BIN
english/basic_content/c_poly/c_examp
Executable file
BIN
english/basic_content/c_poly/c_examp
Executable file
Binary file not shown.
55
english/basic_content/c_poly/c_examp.c
Normal file
55
english/basic_content/c_poly/c_examp.c
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @file c_examp.c
|
||||
* @brief C实现多态
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-08-06
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/// Define a pointer of function
|
||||
typedef void (*pf) ();
|
||||
|
||||
/**
|
||||
* @brief parent class
|
||||
*/
|
||||
typedef struct _A
|
||||
{
|
||||
pf _f;
|
||||
}A;
|
||||
|
||||
|
||||
/**
|
||||
* @brief child class
|
||||
*/
|
||||
typedef struct _B
|
||||
{
|
||||
A _b; ///< The inheritance of the parent class can be realized by defining an object of the base class in the subclass
|
||||
}B;
|
||||
|
||||
void FunA()
|
||||
{
|
||||
printf("%s\n","Base A::fun()");
|
||||
}
|
||||
|
||||
void FunB()
|
||||
{
|
||||
printf("%s\n","Derived B::fun()");
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
A a;
|
||||
B b;
|
||||
|
||||
a._f = FunA;
|
||||
b._b._f = FunB;
|
||||
|
||||
A *pa = &a;
|
||||
pa->_f();
|
||||
pa = (A *)&b; /// The parent class pointer points to the object of the subclass. Because of the type mismatch, it needs to be forced
|
||||
pa->_f();
|
||||
return 0;
|
||||
}
|
382
english/basic_content/const/README.md
Normal file
382
english/basic_content/const/README.md
Normal file
@ -0,0 +1,382 @@
|
||||
|
||||
|
||||
|
||||
## 1.The Definition Of const
|
||||
|
||||
Const type is that people use type specifier **const** signiture type to demonstrate,const variables or objects can not be updated。
|
||||
|
||||
## 2. Effect Of Const
|
||||
|
||||
(1)define variable
|
||||
|
||||
```
|
||||
const int a=100;
|
||||
```
|
||||
|
||||
(2) check type
|
||||
|
||||
The difference between const variable and define variable: ~~<u>**Constants have types, which can be checked by the compiler; the define macro definition has no data type, it is just a simple string replacement, and cannot be checked for security
|
||||
**</u>~~ Thanks for point this bug out.
|
||||
> https://github.com/Light-City/CPlusPlusThings/issues/5
|
||||
|
||||
Only variables of type integer or enumeration are defined by `const`. In other cases, it is only a 'const' qualified variable and should not be confused with constants.
|
||||
|
||||
(3)prevent modification, protect and increase program robustness
|
||||
|
||||
|
||||
```
|
||||
void f(const int i){
|
||||
i++; //error!
|
||||
}
|
||||
```
|
||||
(4)Save space and avoid unnecessary memory allocation
|
||||
|
||||
From the compile point of view, the variables can be defined by const only give the corresponding memory address. Meanwhile the #define gives an immediate number.
|
||||
|
||||
## 3.const object is the file local variable by default
|
||||
|
||||
|
||||
<p><font style="color:red">Attention:not const will be set as extern by default.For the const variable to be accessible in other files, it must be explicitly specified as extern in the file
|
||||
|
||||
</font></p>
|
||||
> Access of variables not modified by const in different files
|
||||
|
||||
|
||||
```
|
||||
// file1.cpp
|
||||
int ext
|
||||
// file2.cpp
|
||||
#include<iostream>
|
||||
/**
|
||||
* by 光城
|
||||
* compile: g++ -o file file2.cpp file1.cpp
|
||||
* execute: ./file
|
||||
*/
|
||||
extern int ext;
|
||||
int main(){
|
||||
std::cout<<(ext+10)<<std::endl;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
You can find that variables that are not modified by const do not need to be explicitly declared by extern! Const constants need to be explicitly declared extern and need to be initialized! Because constants cannot be modified after they are defined, they must be initialized
|
||||
|
||||
## 4.Define Variable
|
||||
|
||||
```
|
||||
const int b = 10;
|
||||
b = 0; // error: assignment of read-only variable ‘b’
|
||||
const string s = "helloworld";
|
||||
const int i,j=0 // error: uninitialized const ‘i’
|
||||
```
|
||||
|
||||
There are two errors above. First, B is a constant and cannot be changed! Second: I is a constant and must be initialized! (since constants cannot be modified after definition, they must be initialized. )
|
||||
|
||||
## 5.Pointer and Const
|
||||
There are four kinds of pointer related consts
|
||||
|
||||
```
|
||||
const char * a; //A pointer to a const object, or a pointer to a constant.
|
||||
char const * a; //same as above
|
||||
char * const a; //Const pointer to the type object. Or constant pointer, const pointer.
|
||||
const char * const a; //Const pointer to const object
|
||||
|
||||
```
|
||||
Conclusion: If *const* is on the left of `*`, const is used to modify the variable that the pointer points to, that is, the pointer points to a constant. If *const* is on the right of `*`, then the const is used to modify the pointer itself, that is, the pointer itself is a constant.
|
||||
|
||||
The specific method is as follows:
|
||||
(1) pointer to const:
|
||||
```
|
||||
const int *ptr;
|
||||
*ptr = 10; //error
|
||||
```
|
||||
ptr is a pointer to a const object of type int. Const defines the int type, that is, the type of object PTR points to, not the PTR itself.Therefore, ptr do not need to be assigned an initial value. However, the value of the object in question cannot be modified by ptr. Besides, we can not use void `*` pointer to save the address of const object
|
||||
|
||||
```
|
||||
const int p = 10;
|
||||
const void * vp = &p;
|
||||
void *vp = &p; //error
|
||||
|
||||
```
|
||||
|
||||
Another key point is: we allow the address of a non const object to be assigned to a pointer to a const object.
|
||||
|
||||
Example:
|
||||
```
|
||||
const int *ptr;
|
||||
int val = 3;
|
||||
ptr = &val; //ok
|
||||
```
|
||||
We can't change the val value through the ptr pointer, even if it points to a non const object
|
||||
|
||||
```
|
||||
int *ptr1 = &val;
|
||||
*ptr1=4;
|
||||
cout<<*ptr<<endl;
|
||||
```
|
||||
We cannot modify the underlying object with a pointer to the const object
|
||||
|
||||
However, if the pointer points to a non const object, the object it refers to can be modified in other ways.
|
||||
|
||||
```
|
||||
int *ptr1 = &val;
|
||||
*ptr1=4;
|
||||
cout<<*ptr<<endl;
|
||||
```
|
||||
Conclusion: For a pointer to a constant, the value of the object cannot be modified by the pointer. And You cannot use the void `*` pointer to save the address of the const object. You must use a pointer of type const void `*` to hold the address of the const object.
|
||||
|
||||
(2) Constant pointer
|
||||
|
||||
The const pointer must be initialized and the value of the const pointer cannot be modified.
|
||||
|
||||
```
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
int main(){
|
||||
|
||||
int num=0;
|
||||
int * const ptr=# //const指针必须初始化!且const指针的值不能修改
|
||||
int * t = #
|
||||
*t = 1;
|
||||
cout<<*ptr<<endl;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Modify the value pointed by ptr pointer, which can be modified by non const pointer
|
||||
|
||||
Finally, when the address of a const constant is assigned to ptr, an error will be reported because ptr points to a variable rather than const constant.
|
||||
|
||||
```
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
int main(){
|
||||
const int num=0;
|
||||
int * const ptr=# //error! const int* -> int*
|
||||
cout<<*ptr<<endl;
|
||||
}
|
||||
|
||||
```
|
||||
If changed to const int `*`ptr or const int `*`const ptr, no errors have occurred.
|
||||
|
||||
|
||||
(3) Constant pointer to a constant
|
||||
|
||||
```
|
||||
const int p = 3;
|
||||
const int * const ptr = &p;
|
||||
```
|
||||
|
||||
PTR is a const pointer and then points to a const object of type int
|
||||
|
||||
## 6. Using const in function
|
||||
Return value of const decorated function
|
||||
|
||||
The meaning of const modifying ordinary variables and pointers is basically the same
|
||||
|
||||
(1)const int
|
||||
|
||||
```
|
||||
const int func1();
|
||||
```
|
||||
It doesn't make sense, because the parameter return itself is assigned to other variables
|
||||
|
||||
(2)const int*
|
||||
|
||||
```
|
||||
const int* func2();
|
||||
|
||||
```
|
||||
The pointer points to the same content
|
||||
|
||||
(3)int *const
|
||||
|
||||
```
|
||||
int *const func2();
|
||||
```
|
||||
The pointer itself is immutable
|
||||
|
||||
Const modifier function parameters.
|
||||
|
||||
The passed parameters and pointers themselves are immutable and meaningless in the function.
|
||||
|
||||
|
||||
```
|
||||
void func(const int var); // parameters are immutable
|
||||
void func(int *const var); // point itself is immutable
|
||||
|
||||
```
|
||||
|
||||
(2) Parameter pointer refers to a constant and is immutable
|
||||
|
||||
|
||||
```
|
||||
void StringCopy(char *dst, const char *src);
|
||||
|
||||
```
|
||||
SRC is the input parameter and DST is the output parameter. After adding const modifier to SRC, if the statement in the function body tries to change the contents of SRC, the compiler will point out the error
|
||||
|
||||
This is one of the effects of const.
|
||||
|
||||
(3) The parameter is a reference. In order to increase efficiency and prevent modification at the same time
|
||||
|
||||
```
|
||||
void func(const A &a)
|
||||
```
|
||||
|
||||
For parameters of Non internal data types, Functions such as void func (A, a) are bound to be inefficient. Because a temporary object of type A will be generated in the function body to copy parameter a, and the process of constructing, copying and destructing the temporary object will take time
|
||||
|
||||
To improve efficiency, you can change the function declaration to void func(A &a),Because reference passing only uses aliases for parameters, there is no need to generate temporary objects
|
||||
|
||||
void func(A &a) drawback:
|
||||
It is possible to change the parameter a, which we do not expect.
|
||||
It's easy to solve this problem by adding const modifier
|
||||
|
||||
Finally, it will be : void func(const A &a).
|
||||
|
||||
|
||||
Should void func (int x) be rewritten to void func(const int &x),in order to improve efficiency? That operation was so needless.
|
||||
Because the internal data type parameters do not exist in the process of construction and deconstruction, and replication is very fast.
|
||||
|
||||
Conclusion:For the input parameters of non internal data type, the mode of "value passing" should be changed to "const reference passing", in order to improve the efficiency.
|
||||
For example, change void func (a a a) to void func (const A & A). It can not improve the efficiency and reduce the comprehensibility of the functionVoid func (int x) should not be changed to void func (const int & x).
|
||||
|
||||
So Two interview problems were solved:
|
||||
|
||||
|
||||
(1)If a function needs to pass in a pointer, do you need to add const to the pointer? What is the difference between adding const at different positions of the pointer
|
||||
|
||||
(2)If the function to be written needs to pass in an instance of a complex type, what is the difference between the passed in value parameter or reference parameter, and when to add const to the passed reference parameter
|
||||
## 7.Using const in Class
|
||||
In a class, any function that does not modify data members should be declared as const type. When writing const member functions, if you accidentally modify data members or call other non const member functions, the compiler will point out errors, which will undoubtedly improve the robustness of the program.The member function described by const is called constant member function
|
||||
|
||||
Only constant member functions are qualified to operate constant or constant objects. Member functions without const keyword cannot be used to operate constant objects
|
||||
|
||||
For const member variables in a class, they must be initialized through the initialization list:
|
||||
|
||||
```
|
||||
class Apple
|
||||
{
|
||||
private:
|
||||
int people[100];
|
||||
public:
|
||||
Apple(int i);
|
||||
const int apple_number;
|
||||
};
|
||||
|
||||
Apple::Apple(int i):apple_number(i)
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
Const objects can only access const member functions, while non const objects can access any member functions, including const member functions
|
||||
|
||||
Such as:
|
||||
```
|
||||
//apple.cpp
|
||||
class Apple
|
||||
{
|
||||
private:
|
||||
int people[100];
|
||||
public:
|
||||
Apple(int i);
|
||||
const int apple_number;
|
||||
void take(int num) const;
|
||||
int add(int num);
|
||||
int add(int num) const;
|
||||
int getCount() const;
|
||||
|
||||
};
|
||||
//main.cpp
|
||||
#include<iostream>
|
||||
#include"apple.cpp"
|
||||
using namespace std;
|
||||
|
||||
Apple::Apple(int i):apple_number(i)
|
||||
{
|
||||
|
||||
}
|
||||
int Apple::add(int num){
|
||||
take(num);
|
||||
}
|
||||
int Apple::add(int num) const{
|
||||
take(num);
|
||||
}
|
||||
void Apple::take(int num) const
|
||||
{
|
||||
cout<<"take func "<<num<<endl;
|
||||
}
|
||||
int Apple::getCount() const
|
||||
{
|
||||
take(1);
|
||||
// add(); //error
|
||||
return apple_number;
|
||||
}
|
||||
int main(){
|
||||
Apple a(2);
|
||||
cout<<a.getCount()<<endl;
|
||||
a.add(10);
|
||||
const Apple b(3);
|
||||
b.add(100);
|
||||
return 0;
|
||||
}
|
||||
//Compile: g++ -o main main.cpp apple.cpp
|
||||
//Result
|
||||
take func 1
|
||||
2
|
||||
take func 10
|
||||
take func 100
|
||||
```
|
||||
The getCount () method invokes a add method, and the add method is not const modifier, so run the wrong report. In other words, const objects can only access const member functions. Add method also calls const modified take method, which proves that non const objects can access any member function, including const member function.
|
||||
In addition, we also see an overloaded function of add, which also outputs two results, indicating that const objects call const member functions by default
|
||||
In addition to the above initialization const constant, we can also use the following methods:
|
||||
(1)Combining the definition of constants with static, i.e:
|
||||
```
|
||||
static const int apple_number
|
||||
```
|
||||
(2)Initialize outside:
|
||||
|
||||
```
|
||||
const int Apple::apple_number=10;
|
||||
```
|
||||
Of course, if you use C + + 11 to compile, you can directly define the initialization, you can write:
|
||||
```
|
||||
static const int apple_number=10;
|
||||
or
|
||||
const int apple_number=10;
|
||||
```
|
||||
Both are supported in C + + 11.
|
||||
When compiling, just add '- STD = C + + 11'.
|
||||
Let's talk about static briefly:
|
||||
In C + +, static static member variables cannot be initialized inside a class.It is only declared inside the class, and the definition must be outside the class definition body, usually initialized in the class's implementation file
|
||||
|
||||
Declared in the class:
|
||||
|
||||
```
|
||||
static int ap;
|
||||
```
|
||||
Use in class implementation file
|
||||
```
|
||||
int Apple::ap=666
|
||||
```
|
||||
For this implement, C + + 11 cannot be declared and initialized.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
class Apple
|
||||
{
|
||||
private:
|
||||
int people[100];
|
||||
public:
|
||||
Apple(int i);
|
||||
//使用c++11标准编译
|
||||
static const int apple_number=10;
|
||||
//const int apple_number=10;
|
||||
void take(int num) const;
|
||||
int add(int num);
|
||||
int add(int num) const;
|
||||
int getCount() const;
|
||||
};
|
||||
|
BIN
english/basic_content/const/class_const/c++11_example/main
Executable file
BIN
english/basic_content/const/class_const/c++11_example/main
Executable file
Binary file not shown.
@ -0,0 +1,31 @@
|
||||
#include<iostream>
|
||||
#include"apple.cpp"
|
||||
using namespace std;
|
||||
Apple::Apple(int i)
|
||||
{
|
||||
|
||||
}
|
||||
int Apple::add(int num){
|
||||
take(num);
|
||||
}
|
||||
int Apple::add(int num) const{
|
||||
take(num);
|
||||
}
|
||||
void Apple::take(int num) const
|
||||
{
|
||||
cout<<"take func "<<num<<endl;
|
||||
}
|
||||
int Apple::getCount() const
|
||||
{
|
||||
take(1);
|
||||
// add(); //error
|
||||
return apple_number;
|
||||
}
|
||||
int main(){
|
||||
Apple a(2);
|
||||
cout<<a.getCount()<<endl;
|
||||
a.add(10);
|
||||
const Apple b(3);
|
||||
b.add(100);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
class Apple
|
||||
{
|
||||
private:
|
||||
int people[100];
|
||||
public:
|
||||
Apple(int i);
|
||||
const int apple_number;
|
||||
void take(int num) const;
|
||||
int add(int num);
|
||||
int add(int num) const;
|
||||
int getCount() const;
|
||||
};
|
||||
|
@ -0,0 +1,32 @@
|
||||
#include<iostream>
|
||||
#include"apple.cpp"
|
||||
using namespace std;
|
||||
|
||||
Apple::Apple(int i):apple_number(i)
|
||||
{
|
||||
|
||||
}
|
||||
int Apple::add(int num){
|
||||
take(num);
|
||||
}
|
||||
int Apple::add(int num) const{
|
||||
take(num);
|
||||
}
|
||||
void Apple::take(int num) const
|
||||
{
|
||||
cout<<"take func "<<num<<endl;
|
||||
}
|
||||
int Apple::getCount() const
|
||||
{
|
||||
take(1);
|
||||
// add(); //error
|
||||
return apple_number;
|
||||
}
|
||||
int main(){
|
||||
Apple a(2);
|
||||
cout<<a.getCount()<<endl;
|
||||
a.add(10);
|
||||
const Apple b(3);
|
||||
b.add(100);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
class Apple
|
||||
{
|
||||
private:
|
||||
int people[100];
|
||||
public:
|
||||
Apple(int i);
|
||||
static const int apple_number;
|
||||
void take(int num) const;
|
||||
int add(int num);
|
||||
int add(int num) const;
|
||||
int getCount() const;
|
||||
};
|
||||
|
BIN
english/basic_content/const/class_const/overload_example/main
Executable file
BIN
english/basic_content/const/class_const/overload_example/main
Executable file
Binary file not shown.
@ -0,0 +1,32 @@
|
||||
#include<iostream>
|
||||
#include"apple.cpp"
|
||||
using namespace std;
|
||||
const int Apple::apple_number=10;
|
||||
Apple::Apple(int i)
|
||||
{
|
||||
|
||||
}
|
||||
int Apple::add(int num){
|
||||
take(num);
|
||||
}
|
||||
int Apple::add(int num) const{
|
||||
take(num);
|
||||
}
|
||||
void Apple::take(int num) const
|
||||
{
|
||||
cout<<"take func "<<num<<endl;
|
||||
}
|
||||
int Apple::getCount() const
|
||||
{
|
||||
take(1);
|
||||
// add(); //error
|
||||
return apple_number;
|
||||
}
|
||||
int main(){
|
||||
Apple a(2);
|
||||
cout<<a.getCount()<<endl;
|
||||
a.add(10);
|
||||
const Apple b(3);
|
||||
b.add(100);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
class Apple
|
||||
{
|
||||
private:
|
||||
int people[100];
|
||||
public:
|
||||
Apple(int i);
|
||||
static int ap; //在类实现文件中定义并初始化
|
||||
static const int apple_number;
|
||||
void take(int num) const;
|
||||
int add(int num);
|
||||
int add(int num) const;
|
||||
int getCount() const;
|
||||
};
|
||||
|
BIN
english/basic_content/const/class_const/static_example/main
Executable file
BIN
english/basic_content/const/class_const/static_example/main
Executable file
Binary file not shown.
@ -0,0 +1,34 @@
|
||||
#include<iostream>
|
||||
#include"apple.cpp"
|
||||
using namespace std;
|
||||
const int Apple::apple_number=10;
|
||||
int Apple::ap=666;
|
||||
Apple::Apple(int i)
|
||||
{
|
||||
|
||||
}
|
||||
int Apple::add(int num){
|
||||
take(num);
|
||||
}
|
||||
int Apple::add(int num) const{
|
||||
take(num);
|
||||
}
|
||||
void Apple::take(int num) const
|
||||
{
|
||||
cout<<"take func "<<num<<endl;
|
||||
}
|
||||
int Apple::getCount() const
|
||||
{
|
||||
take(1);
|
||||
// add(); //error
|
||||
return apple_number;
|
||||
}
|
||||
int main(){
|
||||
Apple a(2);
|
||||
cout<<a.getCount()<<endl;
|
||||
cout<<a.ap<<endl;
|
||||
a.add(10);
|
||||
const Apple b(3);
|
||||
b.add(100);
|
||||
return 0;
|
||||
}
|
11
english/basic_content/const/const_function.cpp
Normal file
11
english/basic_content/const/const_function.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
void f(const int i){
|
||||
i=10; // error: assignment of read-only parameter ‘i’
|
||||
cout<<i<<endl;
|
||||
}
|
||||
|
||||
int main(){
|
||||
f(1);
|
||||
}
|
8
english/basic_content/const/const_num.cpp
Normal file
8
english/basic_content/const/const_num.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
int main(){
|
||||
const int b = 10;
|
||||
b = 0; //error
|
||||
const string s = "helloworld";
|
||||
const int i,j=0;
|
||||
}
|
1
english/basic_content/const/extern_const/const_file1.cpp
Normal file
1
english/basic_content/const/extern_const/const_file1.cpp
Normal file
@ -0,0 +1 @@
|
||||
extern const int ext=12;
|
11
english/basic_content/const/extern_const/const_file2.cpp
Normal file
11
english/basic_content/const/extern_const/const_file2.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include<iostream>
|
||||
/**
|
||||
* by 光城
|
||||
* compile: g++ -o file const_file2.cpp const_file1.cpp
|
||||
* execute: ./file
|
||||
*/
|
||||
extern const int ext;
|
||||
int main(){
|
||||
|
||||
std::cout<<ext<<std::endl;
|
||||
}
|
1
english/basic_content/const/extern_const/file1.cpp
Normal file
1
english/basic_content/const/extern_const/file1.cpp
Normal file
@ -0,0 +1 @@
|
||||
int ext;
|
11
english/basic_content/const/extern_const/file2.cpp
Normal file
11
english/basic_content/const/extern_const/file2.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include<iostream>
|
||||
/**
|
||||
* by 光城
|
||||
* compile: g++ -o file file2.cpp file1.cpp
|
||||
* execute: ./file
|
||||
*/
|
||||
extern int ext;
|
||||
int main(){
|
||||
|
||||
std::cout<<(ext+10)<<std::endl;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main(){
|
||||
const int *ptr;
|
||||
*ptr=10; //error
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main(){
|
||||
const int p = 10;
|
||||
const void *vp = &p;
|
||||
void *vp = &p; //error
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
int main(){
|
||||
const int *ptr;
|
||||
int val = 3;
|
||||
ptr = &val; //ok
|
||||
int *ptr1 = &val;
|
||||
*ptr1=4;
|
||||
cout<<*ptr<<endl;
|
||||
|
||||
}
|
BIN
english/basic_content/const/funciton_const/condition2/condition1
Executable file
BIN
english/basic_content/const/funciton_const/condition2/condition1
Executable file
Binary file not shown.
@ -0,0 +1,10 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
int main(){
|
||||
|
||||
int num=0;
|
||||
int * const ptr=# //const指针必须初始化!且const指针的值不能修改
|
||||
int * t = #
|
||||
*t = 1;
|
||||
cout<<*ptr<<endl;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
int main(){
|
||||
|
||||
const int num=0;
|
||||
int * const ptr=# //error! const int* -> int*
|
||||
cout<<*ptr<<endl;
|
||||
}
|
BIN
english/basic_content/const/funciton_const/condition2/condition3
Executable file
BIN
english/basic_content/const/funciton_const/condition2/condition3
Executable file
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
int main(){
|
||||
|
||||
const int num=10;
|
||||
const int * const ptr=# //error! const int* -> int*
|
||||
cout<<*ptr<<endl;
|
||||
}
|
BIN
english/basic_content/const/funciton_const/condition3/condition1
Executable file
BIN
english/basic_content/const/funciton_const/condition3/condition1
Executable file
Binary file not shown.
@ -0,0 +1,10 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
int main(){
|
||||
|
||||
const int p = 3;
|
||||
const int * const ptr = &p;
|
||||
cout<<*ptr<<endl;
|
||||
|
||||
}
|
138
english/basic_content/decltype/README.md
Normal file
138
english/basic_content/decltype/README.md
Normal file
@ -0,0 +1,138 @@
|
||||
# Things about decltype
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
## 1.Basic
|
||||
The syntax of decltype is:
|
||||
|
||||
```
|
||||
decltype (expression)
|
||||
```
|
||||
|
||||
Brackets are essential here.The function of decltype is "the type of query expression".Therefore, the effect of the above statement is to return the type of the expression expression.Note that decltype only "queries" the type of the expression and does not "evaluate" the expression.
|
||||
|
||||
|
||||
### 1.1 Deduce expression type
|
||||
|
||||
```
|
||||
int i = 4;
|
||||
decltype(i) a; //The result is int. The type of a is int
|
||||
```
|
||||
|
||||
### 1.2 Used with using / typedef to define types.
|
||||
|
||||
```c++
|
||||
using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型
|
||||
using ptrdiff_t = decltype((int*)0 - (int*)0);
|
||||
using nullptr_t = decltype(nullptr);
|
||||
vector<int >vec;
|
||||
typedef decltype(vec.begin()) vectype;
|
||||
for (vectype i = vec.begin; i != vec.end(); i++)
|
||||
{
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
like auto, improves the readability of the code.
|
||||
|
||||
|
||||
### 1.3 Reuse anonymous types
|
||||
|
||||
In C + +, we sometimes encounter some anonymous types, such as:
|
||||
|
||||
```c++
|
||||
struct
|
||||
{
|
||||
int d ;
|
||||
doubel b;
|
||||
}anon_s;
|
||||
```
|
||||
|
||||
With decltype, we can reuse this anonymous structure:
|
||||
```c++
|
||||
decltype(anon_s) as ;//Defines an anonymous structure above
|
||||
```
|
||||
|
||||
### 1.4 In generic programming, auto is used to trace the return value type of function
|
||||
|
||||
|
||||
```c++
|
||||
template <typename T>
|
||||
auto multiply(T x, T y)->decltype(x*y)
|
||||
{
|
||||
return x*y;
|
||||
}
|
||||
```
|
||||
|
||||
Code:[decltype.cpp](decltype.cpp)
|
||||
|
||||
## 2.Discriminant rules
|
||||
|
||||
|
||||
|
||||
For decltype (E), the results are affected by the following conditions:
|
||||
If e is a marker expression or class member access expression without parentheses, decltype (E) of is the type of entity named by E.In addition, if e is an overloaded function, it will result in compilation errors.
|
||||
Otherwise, assume that the type of E is t, and if e is a dying value, then decltype (E) is t&&
|
||||
Otherwise, assume that the type of E is t, and if e is a dying value, then decltype (E) is t&&
|
||||
Otherwise, assuming that the type of E is t, decltype (E) is t.
|
||||
|
||||
Markers are defined by programmers except for keywords, literals and other tags that the compiler needs to use. The expression corresponding to a single marker is a marker expression. For example:
|
||||
|
||||
```c++
|
||||
int arr[4]
|
||||
```
|
||||
Then arr is a marker expression,ranther than arr[3]+0
|
||||
|
||||
Example:
|
||||
|
||||
```c++
|
||||
int i = 4;
|
||||
int arr[5] = { 0 };
|
||||
int *ptr = arr;
|
||||
struct S{ double d; }s ;
|
||||
void Overloaded(int);
|
||||
void Overloaded(char);// reload function
|
||||
int && RvalRef();
|
||||
const bool Func(int);
|
||||
|
||||
//Rule 1: derivation is its type
|
||||
decltype (arr) var1; //int 标记符表达式
|
||||
|
||||
decltype (ptr) var2;//int * 标记符表达式
|
||||
|
||||
decltype(s.d) var3;//doubel 成员访问表达式
|
||||
|
||||
//decltype(Overloaded) var4;//重载函数。编译错误。
|
||||
|
||||
//规则二:将亡值。推导为类型的右值引用。
|
||||
|
||||
decltype (RvalRef()) var5 = 1;
|
||||
|
||||
//规则三:Lvalue, derived as a reference to the type
|
||||
|
||||
decltype ((i))var6 = i; //int&
|
||||
|
||||
decltype (true ? i : i) var7 = i; //int& A conditional expression returns an lvalue
|
||||
|
||||
decltype (++i) var8 = i; //int& ++i返回i的左值。
|
||||
|
||||
decltype(arr[5]) var9 = i;//int&. []操作返回左值
|
||||
|
||||
decltype(*ptr)var10 = i;//int& *操作返回左值
|
||||
|
||||
decltype("hello")var11 = "hello"; //const char(&)[9] 字符串字面常量为左值,且为const左值。
|
||||
|
||||
|
||||
//Rule 4: if none of the above is true, this type is derived
|
||||
|
||||
decltype(1) var12;//const int
|
||||
|
||||
decltype(Func(1)) var13=true;//const bool
|
||||
|
||||
decltype(i++) var14 = i;//int i++返回右值
|
||||
```
|
||||
|
||||
From:https://www.cnblogs.com/QG-whz/p/4952980.html
|
BIN
english/basic_content/decltype/decltype
Executable file
BIN
english/basic_content/decltype/decltype
Executable file
Binary file not shown.
60
english/basic_content/decltype/decltype.cpp
Normal file
60
english/basic_content/decltype/decltype.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file decltype.cpp
|
||||
* @brief g++ -o decltype decltype.cpp -std=c++11
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-08-08
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
/**
|
||||
* 泛型编程中结合auto,用于追踪函数的返回值类型
|
||||
*/
|
||||
template <typename T>
|
||||
|
||||
auto multiply(T x, T y)->decltype(x*y)
|
||||
{
|
||||
return x*y;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int nums[] = {1,2,3,4};
|
||||
vector<int> vec(nums,nums+4);
|
||||
vector<int>::iterator it;
|
||||
|
||||
for(it=vec.begin();it!=vec.end();it++)
|
||||
cout<<*it<<" ";
|
||||
cout<<endl;
|
||||
|
||||
|
||||
using nullptr_t = decltype(nullptr);
|
||||
nullptr_t nu;
|
||||
int * p =NULL;
|
||||
if(p==nu)
|
||||
cout<<"NULL"<<endl;
|
||||
|
||||
|
||||
typedef decltype(vec.begin()) vectype;
|
||||
|
||||
for(vectype i=vec.begin();i!=vec.end();i++)
|
||||
cout<<*i<<" ";
|
||||
cout<<endl;
|
||||
|
||||
/**
|
||||
* 匿名结构体
|
||||
*/
|
||||
struct
|
||||
{
|
||||
int d ;
|
||||
double b;
|
||||
}anon_s;
|
||||
|
||||
decltype(anon_s) as; // 定义了一个上面匿名的结构体
|
||||
|
||||
cout<<multiply(11,2)<<endl;
|
||||
|
||||
return 0;
|
||||
}
|
161
english/basic_content/enum/README.md
Normal file
161
english/basic_content/enum/README.md
Normal file
@ -0,0 +1,161 @@
|
||||
# From beginner to Master
|
||||
|
||||
## About author:
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Traditional
|
||||
|
||||
|
||||
Enum has the following problems:
|
||||
|
||||
- The scope is not limited, and it is easy to cause naming conflicts. For example:
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
enum Color {RED,BLUE};
|
||||
enum Feeling {EXCITED,BLUE};
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
- Implicit conversion to int
|
||||
|
||||
- The actual type used to represent an enumerated variable cannot be explicitly specified, Therefore, forward declaration of enumeration types cannot be supported.
|
||||
Implementation:[tradition_color.cpp](tradition_color.cpp)
|
||||
|
||||
## Classic Method
|
||||
|
||||
A simple way to solve the problem of naming conflicts caused by unlimited scope is to prefix the enumeration variables. Change the above example to COLOR_BLUE and FEELING_BLUE。
|
||||
|
||||
Generally speaking, we usually prefix all constants for uniformity.But the code for defining enumeration variables is cumbersome.This may have to be done in the C program. But C++ coder do not like this method。Alternatives is namespace:
|
||||
```c++
|
||||
namespace Color
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
RED=15,
|
||||
YELLOW,
|
||||
BLUE
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Then you can use `Color::Type c = Color::RED;` to define the new enumeration。If after`using namespace Color` ,the prefix can also be omitted to simplify the code.However, the scope closure provided by a namespace is not high because it can be subsequently extended.In large projects, it is still possible for different people to give different things the same enumeration type names.
|
||||
|
||||
A more "effective" approach is to limit its scope with a class or struct.For example:The new variable is defined in the same way as in the namespace above. This way, you don't have to worry about the class being modified elsewhere.We use structs instead of classes because we want these constants to be publicly accessible.
|
||||
|
||||
```c++
|
||||
struct Color1
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
RED=102,
|
||||
YELLOW,
|
||||
BLUE
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Implementation:[classic_practice.cpp](classic_practice.cpp)
|
||||
|
||||
## C++11 Enum class
|
||||
|
||||
The above approach solves the first problem, but it can not do anything for the latter two.Fortunately,C ++ 11 standard introduces enum class. It can solve the above problems.
|
||||
|
||||
- The scope of the new enum is no longer global
|
||||
|
||||
- Cannot be implicitly converted to another type
|
||||
|
||||
|
||||
```c++
|
||||
/**
|
||||
* @brief C++11 enum class
|
||||
* Equals to enum class Color2:int
|
||||
*/
|
||||
enum class Color2
|
||||
{
|
||||
RED=2,
|
||||
YELLOW,
|
||||
BLUE
|
||||
};
|
||||
r2 c2 = Color2::RED;
|
||||
cout << static_cast<int>(c2) << endl; //!
|
||||
```
|
||||
|
||||
- You can specify a specific type to store enum
|
||||
|
||||
```c++
|
||||
enum class Color3:char; // Forward statement
|
||||
|
||||
// Definition
|
||||
enum class Color3:char
|
||||
{
|
||||
RED='r',
|
||||
BLUE
|
||||
};
|
||||
char c3 = static_cast<char>(Color3::RED);
|
||||
```
|
||||
|
||||
Implementation:[classic_practice.cpp](classic_practice.cpp)
|
||||
|
||||
## Enum types in class
|
||||
|
||||
|
||||
|
||||
Sometimes we want certain constants to work only in classes. Because the macro constant defined by a is global, it can not achieve the purpose, so we want to use const to modify data members.The const data member does exist, but its meaning is not what we expected.
|
||||
Data members are constants only for the lifetime of an objec. However, it is variable for the whole class, because the class can create multiple objects, and the values of const data members of different objects can be different.
|
||||
|
||||
|
||||
|
||||
Cannot be initialized in a class declaration const data memeber。The following usage is incorrect,Because the compiler does not know what the value of size is when the object of the class is not created.(c++11)
|
||||
|
||||
```c++
|
||||
class A
|
||||
{
|
||||
const int SIZE = 100; // Error,Attempt to initialize const data member in class declaration
|
||||
int array[SIZE]; // Error,Unknown size
|
||||
};
|
||||
```
|
||||
|
||||
This should be done in the initialization list of the class's constructor:
|
||||
|
||||
```c++
|
||||
class A
|
||||
{
|
||||
A(int size); // Constructor
|
||||
const int SIZE ;
|
||||
};
|
||||
A::A(int size) : SIZE(size) // The definition of Struct
|
||||
{
|
||||
|
||||
}
|
||||
A a(100); // The size of Object A is 100
|
||||
A b(200); // The size of Object B is 200
|
||||
```
|
||||
|
||||
How can I establish constants that are constant throughout a class?
|
||||
|
||||
It should be implemented with enumeration constants in the class. Such as:
|
||||
|
||||
```c++
|
||||
class Person{
|
||||
public:
|
||||
typedef enum {
|
||||
BOY = 0,
|
||||
GIRL
|
||||
}SexType;
|
||||
};
|
||||
//Access via Person::BOY or Person::GIRL.
|
||||
```
|
||||
|
||||
Enum constants do not take up the storage space of the object . They are all evaluated at compile time
|
||||
|
||||
|
||||
Drawback of Enum:Its implied data type is an integer, the maximum is limited, and it cannot represent floating point.
|
BIN
english/basic_content/enum/classic_practice
Executable file
BIN
english/basic_content/enum/classic_practice
Executable file
Binary file not shown.
87
english/basic_content/enum/classic_practice.cpp
Normal file
87
english/basic_content/enum/classic_practice.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @file classic_practice.cpp
|
||||
* @brief g++ -o classic_practice classic_practice.cpp -std=c++11
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-08-07
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
/**
|
||||
* @brief namespace解决作用域不受限
|
||||
*/
|
||||
namespace Color
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
RED=15,
|
||||
YELLOW,
|
||||
BLUE
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 上述如果 using namespace Color 后,前缀还可以省去,使得代码简化。
|
||||
* 不过,因为命名空间是可以随后被扩充内容的,所以它提供的作用域封闭性不高。
|
||||
* 在大项目中,还是有可能不同人给不同的东西起同样的枚举类型名。
|
||||
* 更“有效”的办法是用一个类或结构体来限定其作用域。
|
||||
*
|
||||
* 定义新变量的方法和上面命名空间的相同。
|
||||
* 不过这样就不用担心类在别处被修改内容。
|
||||
* 这里用结构体而非类,一是因为本身希望这些常量可以公开访问,
|
||||
* 二是因为它只包含数据没有成员函数。
|
||||
*/
|
||||
struct Color1
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
RED=102,
|
||||
YELLOW,
|
||||
BLUE
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief C++11的枚举类
|
||||
* 下面等价于enum class Color2:int
|
||||
*/
|
||||
enum class Color2
|
||||
{
|
||||
RED=2,
|
||||
YELLOW,
|
||||
BLUE
|
||||
};
|
||||
|
||||
enum class Color3:char; // 前向声明
|
||||
|
||||
// 定义
|
||||
enum class Color3:char
|
||||
{
|
||||
RED='r',
|
||||
BLUE
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// 定义新的枚举变量
|
||||
Color::Type c = Color::RED;
|
||||
cout<<c<<endl;
|
||||
/**
|
||||
* 上述的另一种方法:
|
||||
* using namespace Color; // 定义新的枚举变量
|
||||
* Type c = RED;
|
||||
*/
|
||||
Color1 c1;
|
||||
cout<<c1.RED<<endl;
|
||||
|
||||
Color1::Type c11 = Color1::BLUE;
|
||||
cout<<c11<<endl;
|
||||
|
||||
Color2 c2 = Color2::RED;
|
||||
cout << static_cast<int>(c2) << endl;
|
||||
|
||||
char c3 = static_cast<char>(Color3::RED);
|
||||
cout<<c3<<endl;
|
||||
return 0;
|
||||
}
|
10
english/basic_content/enum/tradition_color.cpp
Normal file
10
english/basic_content/enum/tradition_color.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
enum Color {RED,BLUE};
|
||||
enum Feeling {EXCITED,BLUE};
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
15
english/basic_content/explicit/README.md
Normal file
15
english/basic_content/explicit/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Things about explicit
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
- explicit When decorating a constructor, you can prevent implicit conversion and copy initialization
|
||||
- explicit When modifying a conversion function, you can prevent implicit conversion, except for context conversion
|
||||
|
||||
|
||||
Code :[.explicit.cpp](./explicit.cpp)
|
||||
|
||||
Reference Link:
|
||||
> https://stackoverflow.com/questions/4600295/what-is-the-meaning-of-operator-bool-const
|
BIN
english/basic_content/explicit/explicit
Executable file
BIN
english/basic_content/explicit/explicit
Executable file
Binary file not shown.
46
english/basic_content/explicit/explicit.cpp
Normal file
46
english/basic_content/explicit/explicit.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct A
|
||||
{
|
||||
A(int) { }
|
||||
operator bool() const { return true; }
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
explicit B(int) {}
|
||||
explicit operator bool() const { return true; }
|
||||
};
|
||||
|
||||
void doA(A a) {}
|
||||
|
||||
void doB(B b) {}
|
||||
|
||||
int main()
|
||||
{
|
||||
A a1(1); // OK:直接初始化
|
||||
A a2 = 1; // OK:复制初始化
|
||||
A a3{ 1 }; // OK:直接列表初始化
|
||||
A a4 = { 1 }; // OK:复制列表初始化
|
||||
A a5 = (A)1; // OK:允许 static_cast 的显式转换
|
||||
doA(1); // OK:允许从 int 到 A 的隐式转换
|
||||
if (a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化
|
||||
|
||||
B b1(1); // OK:直接初始化
|
||||
// B b2 = 1; // 错误:被 explicit 修饰构造函数的对象不可以复制初始化
|
||||
B b3{ 1 }; // OK:直接列表初始化
|
||||
// B b4 = { 1 }; // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化
|
||||
B b5 = (B)1; // OK:允许 static_cast 的显式转换
|
||||
// doB(1); // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换
|
||||
if (b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
|
||||
bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
|
||||
// bool b7 = b1; // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换
|
||||
bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化
|
||||
|
||||
return 0;
|
||||
}
|
195
english/basic_content/extern/README.md
vendored
Normal file
195
english/basic_content/extern/README.md
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
# extern "C"
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
## 1. Compiler difference between C and C ++
|
||||
|
||||
In C + +, we often see extern "C" modifier function in the header file. What's the effect. Is a function defined in C language module for C + + link.
|
||||
|
||||
Although C + + is compatible with C, the symbols generated by function compilation in C + + files are different from those generated by C language.Because C + + supports function overloading, the symbols generated by C + + function compilation have the information of function parameter type, while C does not.
|
||||
|
||||
|
||||
Take `int add(int a, int b)` for example. The C + + compiler generates the. O file, `add` becomes `add_int_int` and so on, while C would be like this `_add`, that is:For the same function, in C and C + +, the symbols generated after compilation are different.
|
||||
|
||||
This leads to a problem: if the function implemented in C + + is implemented in C language, an error will occur when compiling the link, indicating that the corresponding symbol cannot be found. At this time`extern "C"` works:Tell the linker to find its `_ C `language symbols such as `add` are not modified by C ++.
|
||||
|
||||
## 2.C ++ calls C functions
|
||||
|
||||
When referring to the header file of C, you need to add `extern "C"`
|
||||
|
||||
```c++
|
||||
//add.h
|
||||
#ifndef ADD_H
|
||||
#define ADD_H
|
||||
int add(int x,int y);
|
||||
#endif
|
||||
|
||||
//add.c
|
||||
#include "add.h"
|
||||
|
||||
int add(int x,int y) {
|
||||
return x+y;
|
||||
}
|
||||
|
||||
//add.cpp
|
||||
#include <iostream>
|
||||
#include "add.h"
|
||||
using namespace std;
|
||||
int main() {
|
||||
add(2,3);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile:
|
||||
|
||||
```
|
||||
//Generate add.o file
|
||||
gcc -c add.c
|
||||
```
|
||||
|
||||
Link:
|
||||
|
||||
```
|
||||
g++ add.cpp add.o -o main
|
||||
```
|
||||
|
||||
Without extern "C":
|
||||
|
||||
```c++
|
||||
> g++ add.cpp add.o -o main
|
||||
add.o:在函数‘main’中:
|
||||
add.cpp:(.text+0x0): `main'被多次定义
|
||||
/tmp/ccH65yQF.o:add.cpp:(.text+0x0):第一次在此定义
|
||||
/tmp/ccH65yQF.o:在函数‘main’中:
|
||||
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
|
||||
add.o:在函数‘main’中:
|
||||
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
|
||||
collect2: error: ld returned 1 exit status
|
||||
```
|
||||
|
||||
With extern "C":
|
||||
|
||||
`add.cpp`
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
extern "C" {
|
||||
#include "add.h"
|
||||
}
|
||||
int main() {
|
||||
add(2,3);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
When compiling, you must pay attention to generating intermediate files add.o through GCC
|
||||
|
||||
|
||||
```
|
||||
gcc -c add.c
|
||||
```
|
||||
|
||||
Compile:
|
||||
|
||||
```
|
||||
g++ add.cpp add.o -o main
|
||||
```
|
||||
|
||||
Code:
|
||||
|
||||
- [add.h](extern_c++/add.h)
|
||||
|
||||
- [add.c](extern_c++/add.c)
|
||||
|
||||
- [add.cpp](extern_c++/add.cpp)
|
||||
|
||||
## 2.Calling C++ function in C
|
||||
|
||||
|
||||
`extern "C"` It is a syntax error in C, which needs to be put in the C + + header file.
|
||||
|
||||
```c
|
||||
// add.h
|
||||
#ifndef ADD_H
|
||||
#define ADD_H
|
||||
extern "C" {
|
||||
int add(int x,int y);
|
||||
}
|
||||
#endif
|
||||
|
||||
// add.cpp
|
||||
#include "add.h"
|
||||
|
||||
int add(int x,int y) {
|
||||
return x+y;
|
||||
}
|
||||
|
||||
// add.c
|
||||
extern int add(int x,int y);
|
||||
int main() {
|
||||
add(2,3);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile:
|
||||
|
||||
```c
|
||||
g++ -c add.cpp
|
||||
```
|
||||
|
||||
Link:
|
||||
|
||||
```
|
||||
gcc add.c add.o -o main
|
||||
```
|
||||
|
||||
Code:
|
||||
|
||||
- [add.h](extern_c/add.h)
|
||||
|
||||
- [add.c](extern_c/add.c)
|
||||
|
||||
- [add.cpp](extern_c/add.cpp)
|
||||
|
||||
In the header file of C language, the external function can only be specified as extern type. The declaration of extern "C" is not supported in C language. There will be compiler syntax error when the. C file contains extern "C". Therefore, the use of external "C" is all placed in CPP program related files or its header files.
|
||||
|
||||
|
||||
The following forms are summarized:
|
||||
|
||||
(1)C + + calls C functions:
|
||||
|
||||
```c++
|
||||
//xx.h
|
||||
extern int add(...)
|
||||
|
||||
//xx.c
|
||||
int add(){
|
||||
|
||||
}
|
||||
|
||||
//xx.cpp
|
||||
extern "C" {
|
||||
#include "xx.h"
|
||||
}
|
||||
```
|
||||
|
||||
(2)C calls C + + functions
|
||||
|
||||
```c
|
||||
//xx.h
|
||||
extern "C"{
|
||||
int add();
|
||||
}
|
||||
//xx.cpp
|
||||
int add(){
|
||||
|
||||
}
|
||||
//xx.c
|
||||
extern int add();
|
||||
```
|
||||
|
5
english/basic_content/extern/extern_c++/add.c
vendored
Normal file
5
english/basic_content/extern/extern_c++/add.c
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
#include "add.h"
|
||||
|
||||
int add(int x,int y) {
|
||||
return x+y;
|
||||
}
|
9
english/basic_content/extern/extern_c++/add.cpp
vendored
Normal file
9
english/basic_content/extern/extern_c++/add.cpp
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
extern "C" {
|
||||
#include "add.h"
|
||||
}
|
||||
int main() {
|
||||
add(2,3);
|
||||
return 0;
|
||||
}
|
4
english/basic_content/extern/extern_c++/add.h
vendored
Normal file
4
english/basic_content/extern/extern_c++/add.h
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
#ifndef ADD_H
|
||||
#define ADD_H
|
||||
extern int add(int x,int y);
|
||||
#endif
|
BIN
english/basic_content/extern/extern_c++/add.o
vendored
Normal file
BIN
english/basic_content/extern/extern_c++/add.o
vendored
Normal file
Binary file not shown.
BIN
english/basic_content/extern/extern_c++/main
vendored
Executable file
BIN
english/basic_content/extern/extern_c++/main
vendored
Executable file
Binary file not shown.
5
english/basic_content/extern/extern_c/add.c
vendored
Normal file
5
english/basic_content/extern/extern_c/add.c
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
extern int add(int x,int y);
|
||||
int main() {
|
||||
add(2,3);
|
||||
return 0;
|
||||
}
|
5
english/basic_content/extern/extern_c/add.cpp
vendored
Normal file
5
english/basic_content/extern/extern_c/add.cpp
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
#include "add.h"
|
||||
|
||||
int add(int x,int y) {
|
||||
return x+y;
|
||||
}
|
6
english/basic_content/extern/extern_c/add.h
vendored
Normal file
6
english/basic_content/extern/extern_c/add.h
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef ADD_H
|
||||
#define ADD_H
|
||||
extern "C" {
|
||||
int add(int x,int y);
|
||||
}
|
||||
#endif
|
BIN
english/basic_content/extern/extern_c/add.o
vendored
Normal file
BIN
english/basic_content/extern/extern_c/add.o
vendored
Normal file
Binary file not shown.
BIN
english/basic_content/extern/extern_c/main
vendored
Executable file
BIN
english/basic_content/extern/extern_c/main
vendored
Executable file
Binary file not shown.
111
english/basic_content/friend/README.md
Normal file
111
english/basic_content/friend/README.md
Normal file
@ -0,0 +1,111 @@
|
||||
# Friend and Friend Class
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
## 0.Summary
|
||||
|
||||
Friends provide a mechanism for ordinary functions or class member functions to access private or protected members in another class.In other words, there are two forms of friends:
|
||||
|
||||
(1)Friend Function:Ordinary functions access a private or protected member of a class.
|
||||
|
||||
(2)Friend Class:Member functions in class a access private or protected members in class B
|
||||
|
||||
Advantages: improve the efficiency of the program.
|
||||
|
||||
Disadvantages: it destroys the encapsulation of classes and the transparency of data.
|
||||
Conclusion:
|
||||
- Access to private members
|
||||
- Breaking encapsulation
|
||||
- Friendship is not transitive
|
||||
- The unidirectionality of friend relationship
|
||||
- There are no restrictions on the form and number of friend declarations
|
||||
|
||||
## 1.Friend function
|
||||
|
||||
It is declared in any region of the class declaration, and the definition is outside the class.
|
||||
|
||||
```
|
||||
friend <type><name>(<Parameter table>);
|
||||
```
|
||||
|
||||
Note that the friend function is only a common function, not a class member function of this class. It can be called anywhere. In the friend function, private or protected members of the class can be accessed through the object name.
|
||||
|
||||
Code:[friend_func.cpp](friend_func.cpp)
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
A(int _a):a(_a){};
|
||||
friend int geta(A &ca); ///< Friend function
|
||||
private:
|
||||
int a;
|
||||
};
|
||||
|
||||
int geta(A &ca)
|
||||
{
|
||||
return ca.a;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
A a(3);
|
||||
cout<<geta(a)<<endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 2.Friend Class
|
||||
The declaration of a friend class is in the declaration of the class, and the implementation is outside the class.
|
||||
|
||||
```
|
||||
friend class <friend class name>;
|
||||
```
|
||||
|
||||
Class B is a friend of class A, so class B can directly access private members of A.
|
||||
Code:[friend_class.cpp](friend_class.cpp)
|
||||
```c++
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
A(int _a):a(_a){};
|
||||
friend class B;
|
||||
private:
|
||||
int a;
|
||||
};
|
||||
|
||||
class B
|
||||
{
|
||||
public:
|
||||
int getb(A ca) {
|
||||
return ca.a;
|
||||
};
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
A a(3);
|
||||
B b;
|
||||
cout<<b.getb(a)<<endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 3.Attention
|
||||
- Friendship has no inheritance
|
||||
If class B is a friend of class A and class C inherits from Class A, then friend class B cannot directly access private or protected members of class C.
|
||||
- Friendship is not transitive
|
||||
If class B is a friend of class A and class C is a friend of class B, then friend class C cannot directly access private or protected members of class A, that is, there is no such relationship as "friend of friend".
|
BIN
english/basic_content/friend/friend_class
Executable file
BIN
english/basic_content/friend/friend_class
Executable file
Binary file not shown.
28
english/basic_content/friend/friend_class.cpp
Normal file
28
english/basic_content/friend/friend_class.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
A(int _a):a(_a){};
|
||||
friend class B;
|
||||
private:
|
||||
int a;
|
||||
};
|
||||
|
||||
class B
|
||||
{
|
||||
public:
|
||||
int getb(A ca) {
|
||||
return ca.a;
|
||||
};
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
A a(3);
|
||||
B b;
|
||||
cout<<b.getb(a)<<endl;
|
||||
return 0;
|
||||
}
|
BIN
english/basic_content/friend/friend_func
Executable file
BIN
english/basic_content/friend/friend_func
Executable file
Binary file not shown.
33
english/basic_content/friend/friend_func.cpp
Normal file
33
english/basic_content/friend/friend_func.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @file friend_func.cpp
|
||||
* @brief 友元函数
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-08-06
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
A(int _a):a(_a){};
|
||||
friend int geta(A &ca); ///< 友元函数
|
||||
private:
|
||||
int a;
|
||||
};
|
||||
|
||||
int geta(A &ca)
|
||||
{
|
||||
return ca.a;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
A a(3);
|
||||
cout<<geta(a)<<endl;
|
||||
|
||||
return 0;
|
||||
}
|
BIN
english/basic_content/func_pointer/func1
Executable file
BIN
english/basic_content/func_pointer/func1
Executable file
Binary file not shown.
33
english/basic_content/func_pointer/func_pointer.cpp
Normal file
33
english/basic_content/func_pointer/func_pointer.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @file func_pointer.cpp
|
||||
* @brief 函数指针的使用!
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-20
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* @brief 定义了一个变量pFun,这个变量是个指针,指向返回值和参数都是空的函数的指针!
|
||||
*/
|
||||
void (*pFun)(int);
|
||||
|
||||
/**
|
||||
* @brief 代表一种新类型,不是变量!所以与上述的pFun不一样!
|
||||
*/
|
||||
typedef void (*func)(void);
|
||||
|
||||
void myfunc(void)
|
||||
{
|
||||
cout<<"asda"<<endl;
|
||||
}
|
||||
|
||||
void glFun(int a){ cout<<a<<endl;}
|
||||
int main(){
|
||||
func pfun = myfunc;/*赋值*/
|
||||
pfun();/*调用*/
|
||||
pFun = glFun;
|
||||
(*pFun)(2);
|
||||
}
|
BIN
english/basic_content/img/wechat.jpg
Executable file
BIN
english/basic_content/img/wechat.jpg
Executable file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
141
english/basic_content/inline/README.md
Normal file
141
english/basic_content/inline/README.md
Normal file
@ -0,0 +1,141 @@
|
||||
# Story About Inline
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
## 1.Inline in Class
|
||||
|
||||
Declaration method in header file
|
||||
|
||||
|
||||
```c++
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
void f1(int x);
|
||||
|
||||
/**
|
||||
* @brief The function defined in the class is an implicit inline function. If you want to be an inline function, you must add the inline keyword at the implementation (definition)
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
void Foo(int x,int y) ///< The definition is implicit inline function
|
||||
{
|
||||
|
||||
};
|
||||
void f1(int x); ///< To be an inline function after declaration, you must add the inline keyword to the definition
|
||||
};
|
||||
```
|
||||
|
||||
The inline function is defined in the implementation file:
|
||||
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include "inline.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* @brief To work, inline should be placed with function definition. Inline is a kind of "keyword for implementation, not for declaration"
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int Foo(int x,int y); // Function declaration
|
||||
|
||||
|
||||
inline int Foo(int x,int y) // Function definition
|
||||
{
|
||||
return x+y;
|
||||
}
|
||||
|
||||
// It is recommended to add the keyword "inline" to the definition!
|
||||
inline void A::f1(int x){
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
|
||||
cout<<Foo(1,2)<<endl;
|
||||
|
||||
}
|
||||
/**
|
||||
* Compiler's processing steps for inline function
|
||||
* Copy the body of the inline function to the call point of the inline function;
|
||||
* Allocate memory space for local variables in the inline function used
|
||||
* The input parameters and return values of the inline function are mapped to the local variable space of the calling method
|
||||
* If the inline function has multiple return points, convert it to a branch at the end of the inline function code block (using goto)
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
Inline can improve the efficiency of functions, but not all functions are defined as inline functions!
|
||||
|
||||
-If the execution time of the code in the function body is higher than the cost of function call, the efficiency of receiving goods will be less!
|
||||
|
||||
- On the other hand, every call of inline function will copy the code, which will increase the total code of the program and consume more memory space
|
||||
|
||||
Inline is not suitable for the following situations:
|
||||
|
||||
(1)If the code in the function body is long, it will lead to high memory consumption
|
||||
|
||||
(2)If there is a loop in the function body, it takes more time to execute the code in the function body than the cost of the function call。
|
||||
|
||||
## 2.Could virtual be inline function?
|
||||
|
||||
- Virtual functions can be inline functions, which can modify virtual functions, but cannot be inlined when they are polymorphic
|
||||
- Inline means that the compiler is advised to inline at compile time. However, due to the polymorphism of virtual functions, the compiler cannot know which code to call at runtime. Therefore, when the virtual function is polymorphic (runtime), it cannot be inlined.
|
||||
- `inline virtual` The only time you can inline is when the compiler knows which class the object is calling(such as: `Base::who()`),This only happens if the compiler has an actual object instead of a pointer or reference to the object.
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
inline virtual void who()
|
||||
{
|
||||
cout << "I am Base\n";
|
||||
}
|
||||
virtual ~Base() {}
|
||||
};
|
||||
class Derived : public Base
|
||||
{
|
||||
public:
|
||||
inline void who() //
|
||||
{
|
||||
cout << "I am Derived\n";
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
//
|
||||
Base b;
|
||||
b.who();
|
||||
|
||||
//
|
||||
Base *ptr = new Derived();
|
||||
ptr->who();
|
||||
|
||||
//
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
BIN
english/basic_content/inline/inline
Executable file
BIN
english/basic_content/inline/inline
Executable file
Binary file not shown.
57
english/basic_content/inline/inline.cpp
Normal file
57
english/basic_content/inline/inline.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include <iostream>
|
||||
#include "inline.h"
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* @brief inline要起作用,inline要与函数定义放在一起,inline是一种“用于实现的关键字,而不是用于声明的关键字”
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int Foo(int x,int y); // 函数声明
|
||||
inline int Foo(int x,int y) // 函数定义
|
||||
{
|
||||
return x+y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 定义处加inline关键字,推荐这种写法!
|
||||
inline void A::f1(int x){
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 内联能提高函数效率,但并不是所有的函数都定义成内联函数!内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。
|
||||
* 如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收货会更少!另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
|
||||
* 以下情况不宜用内联:
|
||||
* (1) 如果函数体内的代码比较长,使得内联将导致内存消耗代价比较高。
|
||||
* (2) 如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
|
||||
|
||||
cout<<Foo(1,2)<<endl;
|
||||
|
||||
}
|
||||
/**
|
||||
* 编译器对 inline 函数的处理步骤
|
||||
* 将 inline 函数体复制到 inline 函数调用点处;
|
||||
* 为所用 inline 函数中的局部变量分配内存空间;
|
||||
* 将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
|
||||
* 如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用 GOTO)。
|
||||
*/
|
||||
|
||||
|
||||
|
19
english/basic_content/inline/inline.h
Normal file
19
english/basic_content/inline/inline.h
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
void f1(int x);
|
||||
|
||||
/**
|
||||
* @brief 类中定义了的函数是隐式内联函数,声明要想成为内联函数,必须在实现处(定义处)加inline关键字。
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
void Foo(int x,int y) ///< 定义即隐式内联函数!
|
||||
{
|
||||
|
||||
};
|
||||
void f1(int x); ///< 声明后,要想成为内联函数,必须在定义处加inline关键字。
|
||||
|
||||
};
|
35
english/basic_content/inline/inline_virtual.cpp
Normal file
35
english/basic_content/inline/inline_virtual.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
inline virtual void who()
|
||||
{
|
||||
cout << "I am Base\n";
|
||||
}
|
||||
virtual ~Base() {}
|
||||
};
|
||||
class Derived : public Base
|
||||
{
|
||||
public:
|
||||
inline void who() // 不写inline时隐式内联
|
||||
{
|
||||
cout << "I am Derived\n";
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。
|
||||
Base b;
|
||||
b.who();
|
||||
|
||||
// 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。
|
||||
Base *ptr = new Derived();
|
||||
ptr->who();
|
||||
|
||||
// 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
|
||||
delete ptr;
|
||||
|
||||
return 0;
|
||||
}
|
BIN
english/basic_content/inline/iv
Executable file
BIN
english/basic_content/inline/iv
Executable file
Binary file not shown.
236
english/basic_content/macro/README.md
Normal file
236
english/basic_content/macro/README.md
Normal file
@ -0,0 +1,236 @@
|
||||
# Story about Macro
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
## 1.The macro contains special symbols
|
||||
|
||||
Several type:`#`,`##`,`\`
|
||||
|
||||
### 1.1 String operator(#)
|
||||
|
||||
**Using a # before macro parameter,The preprocessor converts this parameter into an array of characters**,In other words:**# is “stringlize”,The#, which appears in the macro definition, is to convert the following parameter into a string
|
||||
|
||||
**。
|
||||
|
||||
**Attention:It can only be used in macro definitions that have passed in parameters, and must be placed before the parameter name in the macro definition body.**
|
||||
|
||||
For example:
|
||||
|
||||
```c++
|
||||
#define exp(s) printf("test s is:%s\n",s)
|
||||
#define exp1(s) printf("test s is:%s\n",#s)
|
||||
#define exp2(s) #s
|
||||
int main() {
|
||||
exp("hello");
|
||||
exp1(hello);
|
||||
|
||||
string str = exp2( bac );
|
||||
cout<<str<<" "<<str.size()<<endl;
|
||||
/**
|
||||
* Ignore spaces before and after the passed in parameter name
|
||||
*/
|
||||
string str1 = exp2( asda bac );
|
||||
/**
|
||||
* 当传入参数名间存在空格时,编译器将会自动连接各个子字符串,
|
||||
* 用每个子字符串之间以一个空格连接,忽略剩余空格。
|
||||
*/
|
||||
cout<<str1<<" "<<str1.size()<<endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The above code gives the basic use and space handling rules,The space handling rules are as follows:
|
||||
|
||||
- Ignore spaces before and after the passed in parameter name
|
||||
|
||||
```c++
|
||||
string str = exp2( bac );
|
||||
cout<<str<<" "<<str.size()<<endl;
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
bac 3
|
||||
```
|
||||
|
||||
- When there are spaces between the input parameter names, the compiler will automatically connect each substring with a space between each substring, ignoring the remaining spaces.
|
||||
|
||||
```c++
|
||||
string str1 = exp2( asda bac );
|
||||
cout<<str1<<" "<<str1.size()<<endl;
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
asda bac 8
|
||||
```
|
||||
|
||||
### 1.2 Symbolic join operator(##)
|
||||
|
||||
**“##” It's a separate connection. Its function is to separate and then force the connection.Converts multiple parameters defined by a macro to an actual parameter name.**
|
||||
|
||||
Attention:
|
||||
|
||||
**(1)When use ## connecting parameters,##The space before and after is optional**
|
||||
|
||||
**(2)Actual parameter name after connection,Must be an actual parameter name or a macro definition known to the compiler**
|
||||
|
||||
**(3)If ## the parameter itself is a macro,## will prevent the macro from expanding.**
|
||||
|
||||
ex:
|
||||
|
||||
```c++
|
||||
|
||||
#define expA(s) printf("前缀加上后的字符串为:%s\n",gc_##s) //gc_s必须存在
|
||||
// 注意事项2
|
||||
#define expB(s) printf("前缀加上后的字符串为:%s\n",gc_ ## s) //gc_s必须存在
|
||||
// 注意事项1
|
||||
#define gc_hello1 "I am gc_hello1"
|
||||
int main() {
|
||||
// 注意事项1
|
||||
const char * gc_hello = "I am gc_hello";
|
||||
expA(hello);
|
||||
expB(hello1);
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 Continuation operator(\)
|
||||
|
||||
**When the defined macro cannot be expressed completely in one line, you can use "\" to indicate the next line to continue the macro definition **
|
||||
|
||||
**Leave a space before \ **
|
||||
|
||||
```c++
|
||||
#define MAX(a,b) ((a)>(b) ? (a) \
|
||||
:(b))
|
||||
int main() {
|
||||
int max_val = MAX(3,6);
|
||||
cout<<max_val<<endl;
|
||||
}
|
||||
```
|
||||
|
||||
From:[sig_examp.cpp](sig_examp.cpp)
|
||||
|
||||
## 2.do{...}while(0)
|
||||
|
||||
### 2.1 Avoid semantic misinterpretation
|
||||
|
||||
Such as :
|
||||
|
||||
```
|
||||
#define fun() f1();f2();
|
||||
if(a>0)
|
||||
fun()
|
||||
```
|
||||
|
||||
When this macro is expanded, it will be:
|
||||
|
||||
```
|
||||
if(a>0)
|
||||
f1();
|
||||
f2();
|
||||
```
|
||||
|
||||
|
||||
In order to solve this problem, when writing code, usually can adopt
|
||||
|
||||
`{}`。
|
||||
|
||||
ex:
|
||||
|
||||
```c++
|
||||
#define fun() {f1();f2();}
|
||||
if(a>0)
|
||||
fun();
|
||||
// 宏展开
|
||||
if(a>0)
|
||||
{
|
||||
f1();
|
||||
f2();
|
||||
};
|
||||
```
|
||||
|
||||
However, you will find that there is a semicolon after the macro is expanded, so the actual syntax is not correct.(Although the compiler runs well, there is no semicolon).
|
||||
|
||||
### 2.2 Avoid using goto to control flow
|
||||
|
||||
In some functions, we may need to do some cleaning before the return statement, such as releasing the memory space requested by malloc at the beginning of the function. Using goto is always a simple method:
|
||||
|
||||
|
||||
```c++
|
||||
int f() {
|
||||
int *p = (int *)malloc(sizeof(int));
|
||||
*p = 10;
|
||||
cout<<*p<<endl;
|
||||
#ifndef DEBUG
|
||||
int error=1;
|
||||
#endif
|
||||
if(error)
|
||||
goto END;
|
||||
// dosomething
|
||||
END:
|
||||
cout<<"free"<<endl;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
However, because go to does not conform to the structure of software engineering and may make the code difficult to understand, many people do not advocate using goto. At this time, we can use do {...} while (0) to do the same thing
|
||||
|
||||
|
||||
```c++
|
||||
int ff() {
|
||||
int *p = (int *)malloc(sizeof(int));
|
||||
*p = 10;
|
||||
cout<<*p<<endl;
|
||||
do{
|
||||
#ifndef DEBUG
|
||||
int error=1;
|
||||
#endif
|
||||
if(error)
|
||||
break;
|
||||
//dosomething
|
||||
}while(0);
|
||||
cout<<"free"<<endl;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The main part of function using do{...}while(0),using break instead of goto.The subsequent cleaning is after while. Now we can achieve the same effect, and the readability and maintainability of the code are better than the goto code above
|
||||
|
||||
### 2.3 Avoid warnings caused by macros
|
||||
|
||||
|
||||
Due to the limitation of different architectures in the kernel,Empty macros are often used. While compiling,These empty macros give warning. In order to avoid warning,we could use do{...}while(0) to define empty macro:
|
||||
|
||||
```
|
||||
#define EMPTYMICRO do{}while(0)
|
||||
```
|
||||
|
||||
### 2.4 **Define a single function block to perform complex operations**
|
||||
|
||||
If you have a complex function. There are many variables,And you don't want to add new functions。You could use do {...}while(0),Write your code in it. You can define variables without considering the repetition of variable names and functions.
|
||||
This should mean that a variable is used in multiple place(But the meaning of each is different),We can narrow down the scope in each do while,for example:
|
||||
|
||||
```c++
|
||||
int fc()
|
||||
{
|
||||
int k1 = 10;
|
||||
cout<<k1<<endl;
|
||||
do{
|
||||
int k1 = 100;
|
||||
cout<<k1<<endl;
|
||||
}while(0);
|
||||
cout<<k1<<endl;
|
||||
}
|
||||
```
|
||||
|
||||
From:[do_while.cpp](do_while.cpp)
|
||||
|
||||
Article:<https://www.cnblogs.com/lizhenghn/p/3674430.html>
|
||||
|
BIN
english/basic_content/macro/do_while
Executable file
BIN
english/basic_content/macro/do_while
Executable file
Binary file not shown.
76
english/basic_content/macro/do_while.cpp
Normal file
76
english/basic_content/macro/do_while.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include <iostream>
|
||||
#include <malloc.h>
|
||||
|
||||
using namespace std;
|
||||
#define f1() cout<<"f1()"<<endl;
|
||||
#define f2() cout<<"f2()"<<endl;
|
||||
|
||||
#define fun() {f1();f2();}
|
||||
#define fun1() \
|
||||
do{ \
|
||||
f1();\
|
||||
f2();\
|
||||
}while(0)
|
||||
|
||||
int f() {
|
||||
int *p = (int *)malloc(sizeof(int));
|
||||
*p = 10;
|
||||
cout<<*p<<endl;
|
||||
#ifndef DEBUG
|
||||
int error=1;
|
||||
#endif
|
||||
if(error)
|
||||
goto END;
|
||||
|
||||
// dosomething
|
||||
END:
|
||||
cout<<"free"<<endl;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff() {
|
||||
|
||||
int *p = (int *)malloc(sizeof(int));
|
||||
*p = 10;
|
||||
cout<<*p<<endl;
|
||||
|
||||
do{
|
||||
#ifndef DEBUG
|
||||
int error=1;
|
||||
#endif
|
||||
if(error)
|
||||
break;
|
||||
//dosomething
|
||||
}while(0);
|
||||
|
||||
cout<<"free"<<endl;
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int fc()
|
||||
{
|
||||
int k1 = 10;
|
||||
cout<<k1<<endl;
|
||||
do{
|
||||
int k1 = 100;
|
||||
cout<<k1<<endl;
|
||||
}while(0);
|
||||
cout<<k1<<endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
if(1>0)
|
||||
fun();
|
||||
|
||||
if(2>0)
|
||||
fun1();
|
||||
|
||||
f();
|
||||
ff();
|
||||
fc();
|
||||
return 0;
|
||||
}
|
BIN
english/basic_content/macro/sig_examp
Executable file
BIN
english/basic_content/macro/sig_examp
Executable file
Binary file not shown.
86
english/basic_content/macro/sig_examp.cpp
Normal file
86
english/basic_content/macro/sig_examp.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
///===========================================
|
||||
/**
|
||||
* (#)字符串操作符
|
||||
*/
|
||||
///===========================================
|
||||
#define exp(s) printf("test s is:%s\n",s)
|
||||
#define exp1(s) printf("test s is:%s\n",#s)
|
||||
|
||||
#define exp2(s) #s
|
||||
|
||||
|
||||
///===========================================
|
||||
/**
|
||||
*(##)符号连接操作符
|
||||
*/
|
||||
///===========================================
|
||||
#define expA(s) printf("前缀加上后的字符串为:%s\n",gc_##s) //gc_s必须存在
|
||||
|
||||
#define expB(s) printf("前缀加上后的字符串为:%s\n",gc_ ## s) //gc_s必须存在
|
||||
|
||||
#define gc_hello1 "I am gc_hello1"
|
||||
|
||||
|
||||
///===========================================
|
||||
/**
|
||||
* (\)续行操作符
|
||||
*/
|
||||
///===========================================
|
||||
#define MAX(a,b) ((a)>(b) ? (a) \
|
||||
:(b))
|
||||
|
||||
int main() {
|
||||
///===========================================
|
||||
/**
|
||||
* (#)字符串操作符
|
||||
*/
|
||||
///===========================================
|
||||
exp("hello");
|
||||
exp1(hello);
|
||||
|
||||
string str = exp2( bac );
|
||||
cout<<str<<" "<<str.size()<<endl;
|
||||
/**
|
||||
* 忽略传入参数名前面和后面的空格。
|
||||
*/
|
||||
string str1 = exp2( asda bac );
|
||||
/**
|
||||
* 当传入参数名间存在空格时,编译器将会自动连接各个子字符串,
|
||||
* 用每个子字符串之间以一个空格连接,忽略剩余空格。
|
||||
*/
|
||||
cout<<str1<<" "<<str1.size()<<endl;
|
||||
|
||||
///===========================================
|
||||
/**
|
||||
* (#)字符串操作符
|
||||
*/
|
||||
///===========================================
|
||||
|
||||
const char * gc_hello = "I am gc_hello";
|
||||
expA(hello);
|
||||
expB(hello1);
|
||||
|
||||
char var1_p[20];
|
||||
char var2_p[20];
|
||||
|
||||
// 连接后的实际参数名赋值
|
||||
strcpy(var1_p, "aaaa");
|
||||
strcpy(var2_p, "bbbb");
|
||||
|
||||
|
||||
///===========================================
|
||||
/**
|
||||
* (\)续行操作符
|
||||
*/
|
||||
///===========================================
|
||||
int max_val = MAX(3,6);
|
||||
cout<<max_val<<endl;
|
||||
return 0;
|
||||
}
|
BIN
english/basic_content/maohao/.README.md.un~
Normal file
BIN
english/basic_content/maohao/.README.md.un~
Normal file
Binary file not shown.
13
english/basic_content/maohao/README.md
Normal file
13
english/basic_content/maohao/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# :: Story about range resolution operators
|
||||
|
||||
## Abput Author:
|
||||
|
||||
|
||||

|
||||
|
||||
- Global scope(::name):Used before a type name (class, class member, member function, variable, etc.), indicates that the scope is a global namespace
|
||||
- Class scope(class::name):The scope used to represent the specified type is class specific
|
||||
- Namespace scope(namespace::name): The scope used to represent the specified type is a namespace specific
|
||||
|
||||
Code :[maohao.cpp](maohao.cpp)
|
||||
|
14
english/basic_content/maohao/README.md~
Normal file
14
english/basic_content/maohao/README.md~
Normal file
@ -0,0 +1,14 @@
|
||||
# :: 范围解析运算符那些事
|
||||
|
||||
## 关于作者:
|
||||
|
||||
个人公众号:
|
||||
|
||||

|
||||
|
||||
- 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
|
||||
- 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
|
||||
- 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的
|
||||
|
||||
具体代码见:[::.cpp](::.cpp)
|
||||
|
20
english/basic_content/maohao/maohao.cpp
Normal file
20
english/basic_content/maohao/maohao.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
int count=0; // 全局(::)的count
|
||||
|
||||
class A {
|
||||
public:
|
||||
static int count; // 类A的count (A::count)
|
||||
|
||||
};
|
||||
// 静态变量必须在此处定义
|
||||
int A::count;
|
||||
int main() {
|
||||
::count=1; // 设置全局的count为1
|
||||
A::count=5; // 设置类A的count为2
|
||||
cout<<A::count<<endl;
|
||||
// int count=3; // 局部count
|
||||
// count=4; // 设置局部的count为4
|
||||
return 0;
|
||||
}
|
179
english/basic_content/pointer_refer/README.md
Normal file
179
english/basic_content/pointer_refer/README.md
Normal file
@ -0,0 +1,179 @@
|
||||
# Reference and Pointer
|
||||
|
||||
## About Author:
|
||||
|
||||
|
||||

|
||||
|
||||
## 1.References and pointers
|
||||
|
||||
Conclusion:
|
||||
|
||||
| Reference | Pointer |
|
||||
| ------------ | ------------ |
|
||||
| Must be initialized | No initialization is allowed |
|
||||
| cannot be empty | could be empty |
|
||||
| Target cannot be changed | could change target |
|
||||
|
||||
> References must be initialized, and pointers can be uninitialized
|
||||
|
||||
When we define a reference, we must specify an initial value for it, but the pointer does not
|
||||
|
||||
```c++
|
||||
int &r; //Illegal, no initialization reference
|
||||
int *p; //It is legal, but p is a wild pointer. You should be careful when using it
|
||||
```
|
||||
|
||||
> Reference cannot be null and pointer can be null
|
||||
|
||||
Since the reference cannot be null, we do not need to test its validity when using a reference. When using a pointer, we need to first judge whether the pointer is a null pointer, otherwise it may cause the program to crash.
|
||||
```c++
|
||||
void test_p(int* p)
|
||||
{
|
||||
if(p != null_ptr) //
|
||||
*p = 3;
|
||||
return;
|
||||
}
|
||||
void test_r(int& r)
|
||||
{
|
||||
r = 3; //
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
> References cannot change targets
|
||||
|
||||
|
||||
|
||||
The pointer can be changed at any time, but the reference can only point to the object pointed to during initialization, and cannot be changed.
|
||||
|
||||
|
||||
```
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
|
||||
int &r = a; //
|
||||
int *p = &a; //
|
||||
|
||||
p = &b; //
|
||||
r = b; //引
|
||||
```
|
||||
|
||||
## 2.Reference
|
||||
|
||||
#### lvalue reference
|
||||
|
||||
General reference, which generally represents the identity of an object.
|
||||
|
||||
|
||||
#### rvalue reference
|
||||
|
||||
|
||||
|
||||
An R-value reference is a reference that must be bound to an R-value (a temporary object, an object to be destroyed), and generally represents the value of an object.
|
||||
|
||||
|
||||
An R-value reference is a reference that must be bound to an R-value (a temporary object, an object to be destroyed), and generally represents the value of an object.
|
||||
|
||||
- It eliminates unnecessary copy of objects when two objects interact, saves operation storage resources and improves efficiency
|
||||
- It can define generic functions more concisely and clearly
|
||||
|
||||
#### Reference collapse
|
||||
|
||||
- `X& &`、`X& &&`、`X&& &` can be folded into `X&`
|
||||
- `X&& &&` can be floded into `X&&`
|
||||
|
||||
The reference of C ++ **At the same time, it improves the security of memory operation and the beauty of semantics**。For example, the mandatory requirement of reference must be initialized, so that we don't have to judge whether the reference is empty when using the reference, which makes the code more concise and elegant, and avoids the situation of pointer flying all over the sky. In addition to this scenario, references are used for the following two scenarios:
|
||||
|
||||
> Reference type parameter
|
||||
|
||||
In general, we use const reference parameter as a read-only formal parameter. In this case, we can not only avoid parameter copy, but also get the same call method as value passing parameter.
|
||||
|
||||
```c++
|
||||
void test(const vector<int> &data)
|
||||
{
|
||||
//...
|
||||
}
|
||||
int main()
|
||||
{
|
||||
vector<int> data{1,2,3,4,5,6,7,8};
|
||||
test(data);
|
||||
}
|
||||
```
|
||||
|
||||
> Reference type return value
|
||||
|
||||
C++ Provides the ability to overload operators.The syntax of the overloaded operator is the same as that of the original operator.An example is the operator [] operator, which generally needs to return a reference object in order to be modified correctly.
|
||||
|
||||
```c++
|
||||
vector<int> v(10);
|
||||
v[5] = 10; //[]Operator returns the reference, and then the corresponding element of vector can be modified
|
||||
//If[] operator do not return a reference but a pointer, the assignment statement needs to be written like this
|
||||
*v[5] = 10; // This way of writing is totally inconsistent with our understanding of the call of [], which is easy to be misunderstood
|
||||
```
|
||||
|
||||
## 3.Performance gap between pointer and reference
|
||||
|
||||
Is there a performance gap between pointers and references?This kind of problem needs to enter the assembly level to have a look. Let's first write a test1 function, which uses pointers for parameter passing:
|
||||
|
||||
```c++
|
||||
void test1(int* p)
|
||||
{
|
||||
*p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
The assembly code corresponding to this code segment is as follows:
|
||||
|
||||
```c++
|
||||
(gdb) disassemble
|
||||
Dump of assembler code for function test1(int*):
|
||||
0x0000000000400886 <+0>: push %rbp
|
||||
0x0000000000400887 <+1>: mov %rsp,%rbp
|
||||
0x000000000040088a <+4>: mov %rdi,-0x8(%rbp)
|
||||
=> 0x000000000040088e <+8>: mov -0x8(%rbp),%rax
|
||||
0x0000000000400892 <+12>: movl $0x3,(%rax)
|
||||
0x0000000000400898 <+18>: nop
|
||||
0x0000000000400899 <+19>: pop %rbp
|
||||
0x000000000040089a <+20>: retq
|
||||
End of assembler dump.
|
||||
|
||||
```
|
||||
|
||||
The above code lines 1 and 2 are the field operation of parameter calling and saving;The third line is parameter passing. The first parameter of the function call is usually placed in the RDI register. This line of code writes the RDI register value (the value of pointer P) to the stack;Line 4 writes the value of P in the stack to the rax register;Line 5 is to write the immediate number 3 to the**Memory pointed to by the value of the rax register**.
|
||||
|
||||
Let's write out the reference C + + code segment test2 for parameter passing:
|
||||
|
||||
```c++
|
||||
void test2(int& r)
|
||||
{
|
||||
r = 3; // do not need to judge whether reference is null.
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
This code corresponds to the following assembly code:
|
||||
|
||||
```c++
|
||||
(gdb) disassemble
|
||||
Dump of assembler code for function test2(int&):
|
||||
0x000000000040089b <+0>: push %rbp
|
||||
0x000000000040089c <+1>: mov %rsp,%rbp
|
||||
0x000000000040089f <+4>: mov %rdi,-0x8(%rbp)
|
||||
=> 0x00000000004008a3 <+8>: mov -0x8(%rbp),%rax
|
||||
0x00000000004008a7 <+12>: movl $0x3,(%rax)
|
||||
0x00000000004008ad <+18>: nop
|
||||
0x00000000004008ae <+19>: pop %rbp
|
||||
0x00000000004008af <+20>: retq
|
||||
End of assembler dump.
|
||||
|
||||
```
|
||||
|
||||
We find that the assembly code corresponding to test2 is exactly the same as that of test1.This shows that the C + + compiler compiles the pointer and reference into exactly the same machine code when compiling the program. Therefore, the reference in C + + is just a "syntax sugar" of pointer operation in C ++,In the underlying implementation, the C + + compiler implements these two operations in the same way.
|
||||
|
||||
## 3. Conclusion
|
||||
|
||||
The introduction of reference operation in C + + ensures the security and convenience of reference use and maintains the elegance of code under the condition of adding more restrictions on the use of reference. The use of reference can avoid the situation of "pointer flying all over the sky" to a certain extent, and it has a positive significance to improve the stability of the program. Finally, the underlying implementations of pointers and references are the same, and there is no need to worry about the performance gap between them.
|
||||
|
||||
From:<http://irootlee.com/juicer_pointer_reference/#>
|
BIN
english/basic_content/pointer_refer/copy_construct
Executable file
BIN
english/basic_content/pointer_refer/copy_construct
Executable file
Binary file not shown.
35
english/basic_content/pointer_refer/copy_construct.cpp
Normal file
35
english/basic_content/pointer_refer/copy_construct.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file copy_construct.cpp
|
||||
* @brief g++ -o copy_construct copy_construct.cpp -fno-elide-constructors
|
||||
* -fno-elide-constructors选项(关闭返回值优化)
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-08-09
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
class Copyable {
|
||||
public:
|
||||
Copyable(){}
|
||||
Copyable(const Copyable &o) {
|
||||
cout << "Copied" << endl;
|
||||
}
|
||||
};
|
||||
Copyable ReturnRvalue() {
|
||||
return Copyable(); //返回一个临时对象
|
||||
}
|
||||
void AcceptVal(Copyable a) {
|
||||
|
||||
}
|
||||
void AcceptRef(const Copyable& a) {
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
cout << "pass by value: " << endl;
|
||||
AcceptVal(ReturnRvalue()); // 应该调用两次拷贝构造函数
|
||||
cout << "pass by reference: " << endl;
|
||||
AcceptRef(ReturnRvalue()); //应该只调用一次拷贝构造函数
|
||||
}
|
BIN
english/basic_content/pointer_refer/effec
Executable file
BIN
english/basic_content/pointer_refer/effec
Executable file
Binary file not shown.
22
english/basic_content/pointer_refer/effec.cpp
Normal file
22
english/basic_content/pointer_refer/effec.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
void test1(int* p)
|
||||
{
|
||||
*p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。
|
||||
return;
|
||||
}
|
||||
|
||||
void test2(int& p)
|
||||
{
|
||||
p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int a=10;
|
||||
int *p=&a;
|
||||
test1(p);
|
||||
test2(a);
|
||||
cout<<a<<endl;
|
||||
return 0;
|
||||
}
|
191
english/basic_content/sizeof/README.md
Normal file
191
english/basic_content/sizeof/README.md
Normal file
@ -0,0 +1,191 @@
|
||||
# Class size calculation
|
||||
|
||||
First of all, let's make a summary, and then we will give an actual example
|
||||
|
||||
- The size of the empty class is 1 byte
|
||||
- In a class, the virtual function itself, member functions (including static and non-static) and static data members do not occupy the storage space of class objects
|
||||
- For classes containing virtual functions, no matter how many virtual functions there are, there is only one virtual pointer, the size of VPTR
|
||||
- Ordinary inheritance, derived class inherits all the functions and members of the base class, and the size is calculated according to byte alignment
|
||||
- Virtual function inheritance, whether single inheritance or multi inheritance, inherits the VPTR of the base class(32 bit operating system 4 bytes, 64 bit operating system 8 bytes)!
|
||||
- Virtual inheritance inherits the VPTR of the base class
|
||||
|
||||
## 1.Rule 1
|
||||
|
||||
```c++
|
||||
/**
|
||||
* @file blackclass.cpp
|
||||
* @brief The size of the empty class is 1 byte
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-21
|
||||
*/
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
class A{};
|
||||
int main()
|
||||
{
|
||||
cout<<sizeof(A)<<endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 2.Rule 2
|
||||
|
||||
```c++
|
||||
/**
|
||||
* @file static.cpp
|
||||
* @brief
|
||||
*
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-21
|
||||
*/
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
class A
|
||||
{
|
||||
public:
|
||||
char b;
|
||||
virtual void fun() {};
|
||||
static int c;
|
||||
static int d;
|
||||
static int f;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
/**
|
||||
* @brief 16
|
||||
*/
|
||||
cout<<sizeof(A)<<endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 3.Rule 3
|
||||
|
||||
```c++
|
||||
/**
|
||||
* @file morevir.cpp
|
||||
* @brief
|
||||
* @author
|
||||
* @version v1
|
||||
* @date 2019-07-21
|
||||
*/
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
class A{
|
||||
virtual void fun();
|
||||
virtual void fun1();
|
||||
virtual void fun2();
|
||||
virtual void fun3();
|
||||
};
|
||||
int main()
|
||||
{
|
||||
cout<<sizeof(A)<<endl; // 8
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 4.Rule 4 and 5
|
||||
|
||||
```c++
|
||||
/**
|
||||
* @file geninhe.cpp
|
||||
* @brief
|
||||
*
|
||||
*
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-21
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
char a;
|
||||
int b;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* char a
|
||||
* int b
|
||||
* short a
|
||||
* long b
|
||||
* 根据字节对齐4+4=8+8+8=24
|
||||
*/
|
||||
class B:A
|
||||
{
|
||||
public:
|
||||
short a;
|
||||
long b;
|
||||
};
|
||||
class C
|
||||
{
|
||||
A a;
|
||||
char c;
|
||||
};
|
||||
class A1
|
||||
{
|
||||
virtual void fun(){}
|
||||
};
|
||||
class C1:public A1
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
cout<<sizeof(A)<<endl; // 8
|
||||
cout<<sizeof(B)<<endl; // 24
|
||||
cout<<sizeof(C)<<endl; // 12
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
cout<<sizeof(C1)<<endl; // 8
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 5.Rule 6
|
||||
|
||||
```c++
|
||||
/**
|
||||
* @file virnhe.cpp
|
||||
* @brief
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-21
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
class A
|
||||
{
|
||||
virtual void fun() {}
|
||||
};
|
||||
class B
|
||||
{
|
||||
virtual void fun2() {}
|
||||
};
|
||||
class C : virtual public A, virtual public B
|
||||
{
|
||||
public:
|
||||
virtual void fun3() {}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
/**
|
||||
* @brief 8 8 16 The derived class inherits multiple virtual functions and inherits the VPTR of all virtual functions
|
||||
*/
|
||||
cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
18
english/basic_content/sizeof/blackclass.cpp
Normal file
18
english/basic_content/sizeof/blackclass.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @file blackclass.cpp
|
||||
* @brief 空类的大小为1字节
|
||||
* @author 光城
|
||||
* @version v1
|
||||
* @date 2019-07-21
|
||||
*/
|
||||
|
||||
#include<iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A{};
|
||||
int main()
|
||||
{
|
||||
cout<<sizeof(A)<<endl;
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user