├── ..gitignore.un~ ├── .README.md.un~ ├── .com.sh.un~ ├── .gitignore ├── .gitignore~ ├── README.md ├── README.md~ ├── basic_content ├── abstract │ ├── README.md │ ├── abstract.cpp │ ├── derived_full.cpp │ ├── interesting_facts1.cpp │ ├── interesting_facts2.cpp │ ├── interesting_facts3.cpp │ ├── interesting_facts4.cpp │ ├── interesting_facts5.cpp │ ├── pure_virtual.cpp │ └── test.cpp ├── assert │ ├── README.md │ ├── assert.c │ └── ignore_assert.c ├── bit │ ├── README.md │ └── learn.cpp ├── c_poly │ ├── README.md │ ├── c++_examp │ ├── c++_examp.cpp │ ├── c_examp │ └── c_examp.c ├── const │ ├── README.md │ ├── class_const │ │ ├── c++11_example │ │ │ ├── apple.cpp │ │ │ ├── main │ │ │ └── main.cpp │ │ ├── first_example │ │ │ ├── apple.cpp │ │ │ └── main.cpp │ │ ├── overload_example │ │ │ ├── apple.cpp │ │ │ ├── main │ │ │ └── main.cpp │ │ └── static_example │ │ │ ├── apple.cpp │ │ │ ├── main │ │ │ └── main.cpp │ ├── const_function.cpp │ ├── const_num.cpp │ ├── extern_const │ │ ├── const_file1.cpp │ │ ├── const_file2.cpp │ │ ├── file1.cpp │ │ └── file2.cpp │ └── funciton_const │ │ ├── condition1 │ │ ├── condition1.cpp │ │ ├── condition2.cpp │ │ └── condition3.cpp │ │ ├── condition2 │ │ ├── condition1 │ │ ├── condition1.cpp │ │ ├── condition2.cpp │ │ ├── condition3 │ │ └── condition3.cpp │ │ └── condition3 │ │ ├── condition1 │ │ └── condition1.cpp ├── decltype │ ├── README.md │ ├── decltype │ └── decltype.cpp ├── enum │ ├── README.md │ ├── classic_practice │ ├── classic_practice.cpp │ └── tradition_color.cpp ├── explicit │ ├── README.md │ ├── explicit │ └── explicit.cpp ├── extern │ ├── README.md │ ├── extern_c++ │ │ ├── add.c │ │ ├── add.cpp │ │ ├── add.h │ │ ├── add.o │ │ └── main │ └── extern_c │ │ ├── add.c │ │ ├── add.cpp │ │ ├── add.h │ │ ├── add.o │ │ └── main ├── friend │ ├── README.md │ ├── friend_class │ ├── friend_class.cpp │ ├── friend_func │ └── friend_func.cpp ├── func_pointer │ ├── func1 │ └── func_pointer.cpp ├── img │ └── wechat.jpg ├── inline │ ├── README.md │ ├── inline │ ├── inline.cpp │ ├── inline.h │ ├── inline_virtual.cpp │ └── iv ├── macro │ ├── README.md │ ├── do_while │ ├── do_while.cpp │ ├── sig_examp │ └── sig_examp.cpp ├── maohao │ ├── .README.md.un~ │ ├── README.md │ ├── README.md~ │ └── maohao.cpp ├── pointer_refer │ ├── README.md │ ├── copy_construct │ ├── copy_construct.cpp │ ├── effec │ └── effec.cpp ├── sizeof │ ├── README.md │ ├── blackclass.cpp │ ├── genA.cpp │ ├── geninhe.cpp │ ├── moreinhe.cpp │ ├── morevir.cpp │ ├── static.cpp │ ├── virinhe.cpp │ └── virmoreinhe.cpp ├── static │ ├── README.md │ ├── demo │ ├── nostatic_class.cpp │ ├── static_class.cpp │ ├── static_demo.cpp │ ├── static_error_variable.cpp │ ├── static_funciton.cpp │ └── static_variable.cpp ├── struct │ ├── README.md │ ├── ext │ ├── ext_struct_func.cpp │ ├── sf │ ├── stff │ ├── struct_func │ ├── struct_func.c │ ├── struct_func.cpp │ ├── struct_func_func.cpp │ └── stu ├── struct_class │ └── README.md ├── this │ ├── README.md │ ├── img │ │ ├── constthis.png │ │ ├── genthis.png │ │ └── thiscontrust.png │ ├── person │ └── person.cpp ├── union │ ├── README.md │ ├── union │ └── union.cpp ├── using │ ├── README.md │ ├── derived_base │ ├── derived_base.cpp │ ├── using_derived │ ├── using_derived.cpp │ ├── using_global │ ├── using_global.cpp │ ├── using_typedef │ └── using_typedef.cpp ├── virtual │ ├── README.md │ ├── set1 │ │ ├── emp │ │ └── emp.cpp │ ├── set2 │ │ └── default_arg.cpp │ ├── set3 │ │ ├── copy_consrtuct.cpp │ │ ├── full_virde.cpp │ │ ├── inline_virtual.cpp │ │ ├── static_error.cpp │ │ ├── vir_con.cpp │ │ ├── vir_de.cpp │ │ ├── virtual_function.cpp │ │ ├── virtual_function1.cpp │ │ └── virtual_inline.cpp │ └── set4 │ │ ├── rtti │ │ ├── rtti.cpp │ │ └── warn_rtti.cpp ├── volatile │ ├── README.md │ ├── noopt_vola.cpp │ ├── nv │ └── volatile.cpp └── vptr_vtable │ ├── README.md │ ├── img │ └── base.jpg │ └── vptr1.cpp ├── c++2.0 └── c++11 │ ├── README.md │ ├── alias.cpp │ ├── auto.cpp │ ├── constexpr.cpp │ ├── decltype.cpp │ ├── default_delete.cpp │ ├── explicit.cpp │ ├── final.cpp │ ├── hash.cpp │ ├── initializer.cpp │ ├── lambda.cpp │ ├── move.cpp │ ├── noexcept.cpp │ ├── nullptr.cpp │ ├── override.cpp │ ├── rvalue.cpp │ ├── template_template.cpp │ ├── tuple.cpp │ ├── type_alias.cpp │ ├── uniform_initialization.cpp │ └── variadic │ ├── variadic.cpp │ ├── variadic1.cpp │ ├── variadic2.cpp │ ├── variadic3_4.cpp │ ├── variadic5.cpp │ ├── variadic6.cpp │ └── variadic7.cpp ├── codingStyleIdioms ├── 1_classInitializers │ ├── 1.1_类之间嵌套.cpp │ ├── 1.2_无默认构造的继承.cpp │ ├── 1.3_类中const数据成员、引用数据成员.cpp │ ├── README.md │ └── initializer.cpp ├── 2_enumclass │ ├── README.md │ └── namespace.cpp ├── 3_RAII │ ├── RAII.cpp │ ├── RAII.md │ ├── RAII_fstram.cpp │ ├── c++_example.cpp │ ├── c++_example1.cpp │ ├── c++_example2.cpp │ └── c_example.cpp ├── 4_copy-swap │ ├── README.md │ └── copy-swapAndADL.cpp ├── 5_pImpl │ ├── .a.cpp.un~ │ ├── .pimplTime.cpp.un~ │ ├── .timePimpl.cpp.un~ │ ├── README.md │ ├── a.cpp~ │ ├── noPimpl.cpp │ ├── pimpl.cpp │ ├── pimplTime.cpp │ ├── pimplTime.cpp~ │ ├── pimplTime.h │ └── timePimpl.cpp~ └── README.md ├── concurrency ├── Threading_In_CPlusPlus │ ├── .idea │ │ ├── Threading_In_CPlusPlus.iml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── workspace.xml │ ├── 1.thread │ │ ├── intro.cpp │ │ └── thread.cpp │ ├── 2.create_type │ │ ├── 1.function_pointer.cpp │ │ ├── 2.lambda_function.cpp │ │ ├── 3.functor.cpp │ │ ├── 4.no_static_member_function.cpp │ │ └── 5.static_member_function.cpp │ ├── 3.join_detach │ │ ├── detach.cpp │ │ └── join.cpp │ ├── 4.mutex │ │ └── critical_section.cpp │ └── CMakeLists.txt └── concurrency_v1 │ ├── chapter1 │ └── 1_helloworld.cpp │ └── chapter2 │ ├── 2.1_basic.cpp │ ├── 2.2_transfer.cpp │ ├── 2.3_ownership.cpp │ ├── 2.4_runtime.cpp │ └── 2_5_id.cpp ├── design_pattern ├── producer_consumer │ └── producer_consumer.cpp └── singleton │ ├── README.md │ ├── barrier_singleton.cpp │ ├── cpulpuls11_singleton.cpp │ ├── dcl_singleton.cpp │ ├── hungrysingleton.cpp │ ├── iazysingleton.cpp │ ├── lock_singleton.cpp │ ├── pthreadoncesingleton.cpp │ └── static_local_singleton.cpp ├── effective_c++ └── 2.cpp ├── epoll ├── README.md ├── epoll_client.cpp ├── epoll_server.cpp ├── test_epoll1.cpp ├── test_epoll2.cpp ├── test_epoll3.cpp └── utility.h ├── extension └── some_problem │ └── string_int.md ├── img └── wechat.jpg ├── ipc ├── README.md ├── mmap.cpp ├── msgqueue.cpp ├── msgqueue_client.cpp ├── msgqueue_server.cpp ├── named_pipe.cpp ├── named_pipe_another.cpp ├── share_memory.cpp ├── share_memory_1.cpp ├── signal.cpp └── unnamed_pipe.cpp ├── learn_class └── modern_C++_30 │ ├── .CMakeLists.txt.un~ │ ├── CMakeLists.txt │ ├── CMakeLists.txt~ │ ├── RAII │ ├── RAII.cpp │ ├── heap.cpp │ └── stack.cpp │ ├── SFINAE │ ├── README.md │ ├── SFINAE.cpp │ ├── SFINAE.pdf │ └── sfinae paper │ │ ├── auto.cpp │ │ ├── blending1.cpp │ │ ├── blending2.cpp │ │ ├── combiningAndGenius.cpp │ │ ├── constexpr.cpp │ │ ├── decltype.cpp │ │ ├── fis_valid.cpp │ │ ├── hana.cpp │ │ ├── is_valid.cpp │ │ ├── lambda.cpp │ │ ├── overload1.cpp │ │ ├── overload2.cpp │ │ ├── p1SFINAE.cpp │ │ ├── p2SFINAE.cpp │ │ ├── packis_valid.cpp │ │ ├── serialize.cpp │ │ ├── sizeof1.cpp │ │ ├── sizeof2.cpp │ │ ├── structData.h │ │ └── timeGenius.cpp │ ├── compilercompute │ ├── IF.cpp │ ├── WhileLoop.cpp │ ├── a.out │ ├── factorial.cpp │ └── fmap.cpp │ ├── compilerpoly │ ├── README.md │ └── template.cpp │ ├── constexpr │ ├── a.out │ ├── container.cpp │ ├── newconstexpr.cpp │ ├── output_container.h │ ├── sqrt.cpp │ └── test3.cpp │ ├── container1 │ ├── container.cpp │ ├── output_container.h │ └── vector_l.cpp │ ├── container2 │ ├── array.cpp │ ├── hash.cpp │ ├── priority_queue.cpp │ ├── relacontainer.cpp │ └── unorder.cpp │ ├── exception │ └── exception.cpp │ ├── functionLambda │ ├── adder.cpp │ ├── autoLambda.cpp │ └── function.cpp │ ├── literalAssert │ ├── assert.cpp │ ├── default_delete.cpp │ ├── literal.cpp │ └── overridefinal.cpp │ ├── memorymodel_atomic │ ├── barrier_singleton.cpp │ ├── cpulpuls11_singleton.cpp │ ├── dcl_singleton.cpp │ ├── hungrysingleton.cpp │ ├── iazysingleton.cpp │ ├── lock_singleton.cpp │ ├── pthreadoncesingleton.cpp │ └── static_local_singleton.cpp │ ├── reference │ ├── collapses.cpp │ ├── don'treturnReference.cpp │ ├── forward.cpp │ ├── lifetime.cpp │ └── reference.cpp │ ├── returnObj │ ├── all.cpp │ ├── returnObj1.cpp │ ├── returnObj2.cpp │ ├── returnObj3.cpp │ ├── returnObj4.cpp │ └── returnObj5.cpp │ └── smart_ptr │ ├── README.md │ ├── auto_scope.cpp │ ├── shared_ptr.cpp │ ├── unique_ptr.cpp │ └── unique_ptr_U.cpp ├── memory_pool └── simple_memory_pool.h ├── practical_exercises ├── .README.md.un~ ├── 10_day_practice │ ├── day1 │ │ ├── 打印练习.cpp │ │ ├── 是否闰年‘.cpp │ │ ├── 注释.cpp │ │ └── 联合体学习.cpp │ ├── day10 │ │ ├── readme.md │ │ └── 文件例题 │ │ │ ├── 12-1.cpp │ │ │ ├── 12-2应用.cpp │ │ │ ├── 12-3.cpp │ │ │ ├── 12-5.cpp │ │ │ ├── 12-6.cpp │ │ │ ├── 12-7.cpp │ │ │ ├── 12-9.cpp │ │ │ ├── 三种输入格式 │ │ │ ├── get()12-2.cpp │ │ │ ├── get(a,size)12-2-1.cpp │ │ │ └── getline()12-2-2.cpp │ │ │ ├── 输出格式10-4.cpp │ │ │ └── 重要!!!课堂练习.cpp │ ├── day2 │ │ ├── x的n次方.cpp │ │ ├── 掷骰子.cpp │ │ ├── 枚举类型.cpp │ │ ├── 求π.cpp │ │ ├── 汉诺塔.cpp │ │ ├── 结构体.cpp │ │ ├── 递归1.cpp │ │ ├── 递归2.cpp │ │ └── 静态变量.cpp │ ├── day3 │ │ ├── 两数交换.cpp │ │ ├── 内联函数.cpp │ │ ├── 函数综合练习题.cpp │ │ ├── 类前向声明.cpp │ │ ├── 静态成员函数1.cpp │ │ ├── 静态成员函数2.cpp │ │ └── 静态数据成员.cpp │ ├── day4 │ │ ├── const用法 │ │ │ ├── readme.md │ │ │ ├── 常对象与常引用.cpp │ │ │ └── 常对象与普通函数.cpp │ │ ├── 友元函数 │ │ │ ├── readme.md │ │ │ ├── 友元模块.cpp │ │ │ └── 友元类.cpp │ │ ├── 拷贝构造函数 │ │ │ ├── clock.cpp │ │ │ └── clock.h │ │ └── 时钟练习题 │ │ │ ├── 重载()的时钟.cpp │ │ │ └── 重载++的时钟.cpp │ ├── day5 │ │ ├── 基类与派生类关系 │ │ │ ├── readme.md │ │ │ └── 基类与派生类(重要).cpp │ │ ├── 构造函数与析构函数 │ │ │ ├── readme.md │ │ │ ├── 构造函数调用次序.cpp │ │ │ ├── 构造顺序.cpp │ │ │ ├── 没有构造函数的派生类.cpp │ │ │ ├── 派生类构造函数.cpp │ │ │ ├── 派生类构造函数调用顺序.cpp │ │ │ └── 派生类给基类传递参数.cpp │ │ ├── 继承访问权限 │ │ │ ├── readme.md │ │ │ ├── 保护成员.cpp │ │ │ ├── 保护继承.cpp │ │ │ ├── 公有继承.cpp │ │ │ └── 私有继承.cpp │ │ ├── 虚拟继承 │ │ │ ├── readme.md │ │ │ ├── 例1.cpp │ │ │ ├── 例2.cpp │ │ │ ├── 派生类初始化.cpp │ │ │ └── 虚基类调用次序(重要).cpp │ │ └── 调用规则 │ │ │ ├── readme.md │ │ │ └── 直接基类与间接基类.cpp │ ├── day6 │ │ ├── readme.md │ │ ├── 纯虚函数和抽象类 │ │ │ └── 抽象类.cpp │ │ └── 虚函数 │ │ │ ├── 从基类继承的成员将访问到派生类版本.cpp │ │ │ ├── 编程实例.cpp │ │ │ ├── 虚函数例子.cpp │ │ │ ├── 虚函数特性.cpp │ │ │ └── 虚析构函数.cpp │ ├── day7 │ │ ├── ()运算符 │ │ │ └── 重载()的时钟.cpp │ │ ├── =号运算符 │ │ │ └── =例题.cpp │ │ ├── []与()例题 │ │ │ └── example1.cpp │ │ ├── []运算符 │ │ │ └── []例题(重点).cpp │ │ ├── readme.md │ │ ├── 一元运算符 │ │ │ ├── 秒钟自增运算.cpp │ │ │ └── 计数器前后自增.cpp │ │ ├── 二元运算符 │ │ │ ├── 1.类运算符重载.cpp │ │ │ └── 2.友元运算符实现.cpp │ │ └── 综合例题 │ │ │ └── 重要.cpp │ ├── day8 │ │ ├── STL │ │ │ └── map_se.cpp │ │ ├── readme.md │ │ ├── 函数模板 │ │ │ ├── 例1.cpp │ │ │ ├── 模板特化.cpp │ │ │ ├── 求最大值.cpp │ │ │ └── 重要.cpp │ │ └── 类模板 │ │ │ ├── 模拟栈.cpp │ │ │ └── 类模板特化.cpp │ ├── day9 │ │ ├── readme.md │ │ └── 异常例子 │ │ │ ├── 1.cpp │ │ │ ├── 10.cpp │ │ │ ├── 2.cpp │ │ │ ├── 3.cpp │ │ │ ├── 4.cpp │ │ │ ├── 5.cpp │ │ │ ├── 6.cpp │ │ │ ├── 7-1.cpp │ │ │ ├── 7.cpp │ │ │ ├── 8.cpp │ │ │ └── 9.cpp │ └── readme.md ├── README.md~ └── key_exercises │ ├── README.md │ ├── 中括号重载.cpp │ ├── 函数模板.cpp │ ├── 动态数组.cpp │ ├── 字典插入与查找.cpp │ ├── 异常捕获.cpp │ ├── 时钟++运算符重载.cpp │ ├── 类模板之栈.cpp │ ├── 类模板特化之数组.cpp │ ├── 继承与封装.cpp │ ├── 读写文件综合题.cpp │ ├── 输入输出运算符重载.cpp │ ├── 输入输出重载.cpp │ ├── 输出格式.cpp │ ├── 运算符重载之强制转换.cpp │ └── 重载圆括号的时钟.cpp ├── smart_ptr ├── README.md ├── test_shared_ptr.cpp ├── test_unique_ptr.cpp ├── test_weak_ptr.cpp └── test_weak_ptr2.cpp ├── src_analysis └── stl │ ├── array.md │ ├── deque.md │ ├── hashtable.md │ ├── iterator.md │ ├── list.md │ ├── map_multimap.md │ ├── myhashtable.md │ ├── queue_stack.md │ ├── rb_tree.md │ ├── set_multiset.md │ ├── traits.md │ ├── typename.md │ ├── unordered_map.md │ ├── vector.md │ └── 谈谈STL设计之EBO优化.md └── tool ├── C++的Debug工具dbg-macro.md ├── output ├── container.cpp └── output_container.h └── 像Python一样玩CC++.md /..gitignore.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/..gitignore.un~ -------------------------------------------------------------------------------- /.README.md.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/.README.md.un~ -------------------------------------------------------------------------------- /.com.sh.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/.com.sh.un~ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | com.sh 2 | -------------------------------------------------------------------------------- /.gitignore~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/.gitignore~ -------------------------------------------------------------------------------- /basic_content/abstract/abstract.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file abstract.cpp 3 | * @brief 抽象类中:在成员函数内可以调用纯虚函数,在构造函数/析构函数内部不能使用纯虚函数 4 | * 如果一个类从抽象类派生而来,它必须实现了基类中的所有纯虚函数,才能成为非抽象类 5 | * @author 光城 6 | * @version v1 7 | * @date 2019-07-20 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | class A { 14 | public: 15 | virtual void f() = 0; // 纯虚函数 16 | void g(){ this->f(); } 17 | A(){} 18 | }; 19 | class B:public A{ 20 | public: 21 | void f(){ cout<<"B:f()"< 10 | using namespace std; 11 | 12 | class Base 13 | { 14 | int x; 15 | public: 16 | virtual void fun() = 0; 17 | int getX() { return x; } 18 | }; 19 | 20 | class Derived: public Base 21 | { 22 | int y; 23 | public: 24 | void fun() { cout << "fun() called"; } // 实现了fun()函数 25 | }; 26 | 27 | int main(void) 28 | { 29 | Derived d; 30 | d.fun(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /basic_content/abstract/interesting_facts1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file interesting_facts1.cpp 3 | * @brief 纯虚函数使一个类变成抽象类 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-07-20 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | /** 13 | * @brief 抽象类至少包含一个纯虚函数 14 | */ 15 | class Test 16 | { 17 | int x; 18 | public: 19 | virtual void show() = 0; 20 | int getX() { return x; } 21 | }; 22 | 23 | int main(void) 24 | { 25 | Test t; //error! 不能创建抽象类的对象 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /basic_content/abstract/interesting_facts2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file interesting_facts2.cpp 3 | * @brief 抽象类类型的指针和引用 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-07-20 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | 13 | /** 14 | * @brief 抽象类至少包含一个纯虚函数 15 | */ 16 | class Base 17 | { 18 | int x; 19 | public: 20 | virtual void show() = 0; 21 | int getX() { return x; } 22 | 23 | }; 24 | class Derived: public Base 25 | { 26 | public: 27 | void show() { cout << "In Derived \n"; } 28 | Derived(){} 29 | }; 30 | int main(void) 31 | { 32 | //Base b; //error! 不能创建抽象类的对象 33 | //Base *b = new Base(); error! 34 | Base *bp = new Derived(); // 抽象类的指针和引用 -> 由抽象类派生出来的类的对象 35 | bp->show(); 36 | return 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /basic_content/abstract/interesting_facts3.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file interesting_facts3.cpp 3 | * @brief 如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类。 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-07-20 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Base 13 | { 14 | int x; 15 | public: 16 | virtual void show() = 0; 17 | int getX() { return x; } 18 | }; 19 | class Derived: public Base 20 | { 21 | public: 22 | // void show() { } 23 | }; 24 | int main(void) 25 | { 26 | Derived d; //error! 派生类没有实现纯虚函数,那么派生类也会变为抽象类,不能创建抽象类的对象 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /basic_content/abstract/interesting_facts4.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file interesting_facts4.cpp 3 | * @brief 抽象类可以有构造函数 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-07-20 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | // An abstract class with constructor 13 | class Base 14 | { 15 | protected: 16 | int x; 17 | public: 18 | virtual void fun() = 0; 19 | Base(int i) { x = i; } 20 | }; 21 | 22 | class Derived: public Base 23 | { 24 | int y; 25 | public: 26 | Derived(int i, int j):Base(i) { y = j; } 27 | void fun() { cout << "x = " << x << ", y = " << y; } 28 | }; 29 | 30 | int main(void) 31 | { 32 | Derived d(4, 5); 33 | d.fun(); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /basic_content/abstract/interesting_facts5.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file interesting_facts5.cpp 4 | * @brief 构造函数不能是虚函数,而析构函数可以是虚析构函数。 5 | * 例如:当基类指针指向派生类对象并删除对象时,我们可能希望调用适当的析构函数。如果析构函数不是虚拟的,则只能调用基类析构函数。 6 | * @author 光城 7 | * @version v1 8 | * @date 2019-07-20 9 | */ 10 | #include 11 | using namespace std; 12 | 13 | class Base { 14 | public: 15 | Base() { cout << "Constructor: Base" << endl; } 16 | virtual ~Base() { cout << "Destructor : Base" << endl; } 17 | }; 18 | 19 | class Derived: public Base { 20 | public: 21 | Derived() { cout << "Constructor: Derived" << endl; } 22 | ~Derived() { cout << "Destructor : Derived" << endl; } 23 | }; 24 | 25 | int main() { 26 | Base *Var = new Derived(); 27 | delete Var; 28 | return 0; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /basic_content/abstract/pure_virtual.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file pure_virtual.cpp 3 | * @brief 纯虚函数:没有函数体的虚函数 4 | * 抽象类:包含纯虚函数的类 5 | * 6 | * @author 光城 7 | * @version v1 8 | * @date 2019-07-20 9 | */ 10 | 11 | #include 12 | 13 | using namespace std; 14 | class A 15 | { 16 | private: 17 | int a; 18 | public: 19 | virtual void show()=0; // 纯虚函数 20 | }; 21 | 22 | 23 | int main() 24 | { 25 | /* 26 | * 1. 抽象类只能作为基类来派生新类使用 27 | * 2. 抽象类的指针和引用->由抽象类派生出来的类的对象! 28 | */ 29 | A a; // error 抽象类,不能创建对象 30 | 31 | A *a1; // ok 可以定义抽象类的指针 32 | 33 | A *a2 = new A(); // error, A是抽象类,不能创建对象 34 | } 35 | -------------------------------------------------------------------------------- /basic_content/abstract/test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test.cpp 3 | * @brief C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它!通过声明中赋值0来声明纯虚函数! 4 | * 纯虚函数:没有函数体的虚函数 5 | * @author 光城 6 | * @version v1 7 | * @date 2019-07-20 8 | */ 9 | 10 | 11 | 12 | /** 13 | * @brief 抽象类 14 | */ 15 | class Test 16 | { 17 | // Data members of class 18 | public: 19 | // Pure Virtual Function 20 | virtual void show() = 0; 21 | 22 | /* Other members */ 23 | }; 24 | -------------------------------------------------------------------------------- /basic_content/assert/README.md: -------------------------------------------------------------------------------- 1 | # assert那些事 2 | 3 | ## 关于作者: 4 | 5 | 个人公众号: 6 | 7 | ![](../img/wechat.jpg) 8 | 9 | 10 | 11 | ## 1.第一个断言案例 12 | 13 | 断言,**是宏,而非函数**。 14 | 15 | assert 宏的原型定义在 (C)、(C++)中。其作用是如果它的条件返回错误,则终止程序执行。 16 | 17 | 可以通过定义 `NDEBUG` 来关闭 assert,**但是需要在源代码的开头,include 之前。** 18 | 19 | ```c 20 | void assert(int expression); 21 | ``` 22 | 23 | > 代码样例:[assert.c](./assert.c) 24 | ```c 25 | #include 26 | #include 27 | 28 | int main() 29 | { 30 | int x = 7; 31 | 32 | /* Some big code in between and let's say x 33 | is accidentally changed to 9 */ 34 | x = 9; 35 | 36 | // Programmer assumes x to be 7 in rest of the code 37 | assert(x==7); 38 | 39 | /* Rest of the code */ 40 | 41 | return 0; 42 | } 43 | ``` 44 | 输出: 45 | ```c 46 | assert: assert.c:13: main: Assertion 'x==7' failed. 47 | ``` 48 | 可以看到输出会把源码文件,行号错误位置,提示出来! 49 | 50 | ## 2.断言与正常错误处理 51 | 52 | + 断言主要用于检查逻辑上不可能的情况。 53 | 54 | >例如,它们可用于检查代码在开始运行之前所期望的状态,或者在运行完成后检查状态。与正常的错误处理不同,断言通常在运行时被禁用。 55 | 56 | + 忽略断言,在代码开头加上: 57 | ```c++ 58 | #define NDEBUG // 加上这行,则 assert 不可用 59 | ``` 60 | 61 | > 样例代码:[ignore_assert.c](./ignore_assert.c) 62 | -------------------------------------------------------------------------------- /basic_content/assert/assert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int x = 7; 7 | 8 | /* Some big code in between and let's say x 9 | * is accidentally changed to 9 */ 10 | x = 9; 11 | 12 | // Programmer assumes x to be 7 in rest of the code 13 | assert(x==7); 14 | 15 | /* Rest of the code */ 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /basic_content/assert/ignore_assert.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ignore_assert.c 3 | * @brief 忽略断言 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-07-25 7 | */ 8 | 9 | # define NDEBUG // 忽略断言 10 | 11 | #include 12 | 13 | int main(){ 14 | int x=7; 15 | assert(x==5); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /basic_content/bit/learn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | struct stuff 5 | { 6 | unsigned int field1: 30; 7 | unsigned int : 2; 8 | unsigned int field2: 4; 9 | unsigned int : 0; 10 | unsigned int field3: 3; 11 | }; 12 | int main(){ 13 | struct stuff s={1,3,5}; 14 | cout< 10 | 11 | using namespace std; 12 | class A 13 | { 14 | public: 15 | virtual void f()//虚函数实现 16 | { 17 | cout << "Base A::f() " << endl; 18 | } 19 | }; 20 | 21 | class B:public A // 必须为共有继承,否则后面调用不到,class默认为私有继承! 22 | { 23 | public: 24 | virtual void f()//虚函数实现,子类中virtual关键字可以没有 25 | { 26 | cout << "Derived B::f() " << endl; 27 | } 28 | }; 29 | 30 | 31 | int main() 32 | { 33 | A a;//基类对象 34 | B b;//派生类对象 35 | 36 | A* pa = &a;//父类指针指向父类对象 37 | pa->f();//调用父类的函数 38 | 39 | pa = &b; //父类指针指向子类对象,多态实现 40 | pa->f();//调用派生类同名函数 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /basic_content/c_poly/c_examp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/c_poly/c_examp -------------------------------------------------------------------------------- /basic_content/c_poly/c_examp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file c_examp.c 3 | * @brief C实现多态 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-08-06 7 | */ 8 | 9 | #include 10 | 11 | /// 重定义一个函数指针类型 12 | typedef void (*pf) (); 13 | 14 | /** 15 | * @brief 父类 16 | */ 17 | typedef struct _A 18 | { 19 | pf _f; 20 | }A; 21 | 22 | 23 | /** 24 | * @brief 子类 25 | */ 26 | typedef struct _B 27 | { 28 | A _b; ///< 在子类中定义一个基类的对象即可实现对父类的继承。 29 | }B; 30 | 31 | void FunA() 32 | { 33 | printf("%s\n","Base A::fun()"); 34 | } 35 | 36 | void FunB() 37 | { 38 | printf("%s\n","Derived B::fun()"); 39 | } 40 | 41 | 42 | int main() 43 | { 44 | A a; 45 | B b; 46 | 47 | a._f = FunA; 48 | b._b._f = FunB; 49 | 50 | A *pa = &a; 51 | pa->_f(); 52 | pa = (A *)&b; /// 让父类指针指向子类的对象,由于类型不匹配所以要进行强转 53 | pa->_f(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /basic_content/const/class_const/c++11_example/apple.cpp: -------------------------------------------------------------------------------- 1 | class Apple 2 | { 3 | private: 4 | int people[100]; 5 | public: 6 | Apple(int i); 7 | //使用c++11标准编译 8 | static const int apple_number=10; 9 | //const int apple_number=10; 10 | void take(int num) const; 11 | int add(int num); 12 | int add(int num) const; 13 | int getCount() const; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /basic_content/const/class_const/c++11_example/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/const/class_const/c++11_example/main -------------------------------------------------------------------------------- /basic_content/const/class_const/c++11_example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include"apple.cpp" 3 | using namespace std; 4 | Apple::Apple(int i) 5 | { 6 | 7 | } 8 | int Apple::add(int num){ 9 | take(num); 10 | } 11 | int Apple::add(int num) const{ 12 | take(num); 13 | } 14 | void Apple::take(int num) const 15 | { 16 | cout<<"take func "< 2 | #include"apple.cpp" 3 | using namespace std; 4 | 5 | Apple::Apple(int i):apple_number(i) 6 | { 7 | 8 | } 9 | int Apple::add(int num){ 10 | take(num); 11 | } 12 | int Apple::add(int num) const{ 13 | take(num); 14 | } 15 | void Apple::take(int num) const 16 | { 17 | cout<<"take func "< 2 | #include"apple.cpp" 3 | using namespace std; 4 | const int Apple::apple_number=10; 5 | Apple::Apple(int i) 6 | { 7 | 8 | } 9 | int Apple::add(int num){ 10 | take(num); 11 | } 12 | int Apple::add(int num) const{ 13 | take(num); 14 | } 15 | void Apple::take(int num) const 16 | { 17 | cout<<"take func "< 2 | #include"apple.cpp" 3 | using namespace std; 4 | const int Apple::apple_number=10; 5 | int Apple::ap=666; 6 | Apple::Apple(int i) 7 | { 8 | 9 | } 10 | int Apple::add(int num){ 11 | take(num); 12 | } 13 | int Apple::add(int num) const{ 14 | take(num); 15 | } 16 | void Apple::take(int num) const 17 | { 18 | cout<<"take func "< 2 | using namespace std; 3 | 4 | void f(const int i){ 5 | i=10; // error: assignment of read-only parameter ‘i’ 6 | cout< 2 | using namespace std; 3 | int main(){ 4 | const int b = 10; 5 | b = 0; //error 6 | const string s = "helloworld"; 7 | const int i,j=0; 8 | } 9 | -------------------------------------------------------------------------------- /basic_content/const/extern_const/const_file1.cpp: -------------------------------------------------------------------------------- 1 | extern const int ext=12; 2 | -------------------------------------------------------------------------------- /basic_content/const/extern_const/const_file2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | /** 3 | * by 光城 4 | * compile: g++ -o file const_file2.cpp const_file1.cpp 5 | * execute: ./file 6 | */ 7 | extern const int ext; 8 | int main(){ 9 | 10 | std::cout< 2 | /** 3 | * by 光城 4 | * compile: g++ -o file file2.cpp file1.cpp 5 | * execute: ./file 6 | */ 7 | extern int ext; 8 | int main(){ 9 | 10 | std::cout<<(ext+10)< 2 | using namespace std; 3 | 4 | 5 | int main(){ 6 | const int *ptr; 7 | *ptr=10; //error 8 | } 9 | -------------------------------------------------------------------------------- /basic_content/const/funciton_const/condition1/condition2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | 5 | int main(){ 6 | const int p = 10; 7 | const void *vp = &p; 8 | void *vp = &p; //error 9 | } 10 | -------------------------------------------------------------------------------- /basic_content/const/funciton_const/condition1/condition3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main(){ 5 | const int *ptr; 6 | int val = 3; 7 | ptr = &val; //ok 8 | int *ptr1 = &val; 9 | *ptr1=4; 10 | cout<<*ptr< 2 | using namespace std; 3 | int main(){ 4 | 5 | int num=0; 6 | int * const ptr=# //const指针必须初始化!且const指针的值不能修改 7 | int * t = # 8 | *t = 1; 9 | cout<<*ptr< 2 | using namespace std; 3 | int main(){ 4 | 5 | const int num=0; 6 | int * const ptr=# //error! const int* -> int* 7 | cout<<*ptr< 2 | using namespace std; 3 | int main(){ 4 | 5 | const int num=10; 6 | const int * const ptr=# //error! const int* -> int* 7 | cout<<*ptr< 2 | using namespace std; 3 | 4 | int main(){ 5 | 6 | const int p = 3; 7 | const int * const ptr = &p; 8 | cout<<*ptr< 10 | #include 11 | using namespace std; 12 | /** 13 | * 泛型编程中结合auto,用于追踪函数的返回值类型 14 | */ 15 | template 16 | 17 | auto multiply(T x, T y)->decltype(x*y) 18 | { 19 | return x*y; 20 | } 21 | 22 | int main() 23 | { 24 | int nums[] = {1,2,3,4}; 25 | vector vec(nums,nums+4); 26 | vector::iterator it; 27 | 28 | for(it=vec.begin();it!=vec.end();it++) 29 | cout<<*it<<" "; 30 | cout< 2 | using namespace std; 3 | 4 | enum Color {RED,BLUE}; 5 | enum Feeling {EXCITED,BLUE}; 6 | 7 | int main() 8 | { 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /basic_content/explicit/README.md: -------------------------------------------------------------------------------- 1 | # explicit(显式)关键字那些事 2 | 3 | ## 关于作者: 4 | 5 | 个人公众号: 6 | 7 | ![](../img/wechat.jpg) 8 | 9 | - explicit 修饰构造函数时,可以防止隐式转换和复制初始化 10 | - explicit 修饰转换函数时,可以防止隐式转换,但按语境转换除外 11 | 12 | 13 | 代码参见:[.explicit.cpp](./explicit.cpp) 14 | 15 | 参考链接: 16 | > https://stackoverflow.com/questions/4600295/what-is-the-meaning-of-operator-bool-const 17 | -------------------------------------------------------------------------------- /basic_content/explicit/explicit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/explicit/explicit -------------------------------------------------------------------------------- /basic_content/extern/extern_c++/add.c: -------------------------------------------------------------------------------- 1 | #include "add.h" 2 | 3 | int add(int x,int y) { 4 | return x+y; 5 | } 6 | -------------------------------------------------------------------------------- /basic_content/extern/extern_c++/add.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | extern "C" { 4 | #include "add.h" 5 | } 6 | int main() { 7 | add(2,3); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /basic_content/extern/extern_c++/add.h: -------------------------------------------------------------------------------- 1 | #ifndef ADD_H 2 | #define ADD_H 3 | extern int add(int x,int y); 4 | #endif 5 | -------------------------------------------------------------------------------- /basic_content/extern/extern_c++/add.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/extern/extern_c++/add.o -------------------------------------------------------------------------------- /basic_content/extern/extern_c++/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/extern/extern_c++/main -------------------------------------------------------------------------------- /basic_content/extern/extern_c/add.c: -------------------------------------------------------------------------------- 1 | extern int add(int x,int y); 2 | int main() { 3 | add(2,3); 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /basic_content/extern/extern_c/add.cpp: -------------------------------------------------------------------------------- 1 | #include "add.h" 2 | 3 | int add(int x,int y) { 4 | return x+y; 5 | } 6 | -------------------------------------------------------------------------------- /basic_content/extern/extern_c/add.h: -------------------------------------------------------------------------------- 1 | #ifndef ADD_H 2 | #define ADD_H 3 | extern "C" { 4 | int add(int x,int y); 5 | } 6 | #endif 7 | -------------------------------------------------------------------------------- /basic_content/extern/extern_c/add.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/extern/extern_c/add.o -------------------------------------------------------------------------------- /basic_content/extern/extern_c/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/extern/extern_c/main -------------------------------------------------------------------------------- /basic_content/friend/friend_class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/friend/friend_class -------------------------------------------------------------------------------- /basic_content/friend/friend_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class A 6 | { 7 | public: 8 | A(int _a):a(_a){}; 9 | friend class B; 10 | private: 11 | int a; 12 | }; 13 | 14 | class B 15 | { 16 | public: 17 | int getb(A ca) { 18 | return ca.a; 19 | }; 20 | }; 21 | 22 | int main() 23 | { 24 | A a(3); 25 | B b; 26 | cout< 10 | 11 | using namespace std; 12 | 13 | class A 14 | { 15 | public: 16 | A(int _a):a(_a){}; 17 | friend int geta(A &ca); ///< 友元函数 18 | private: 19 | int a; 20 | }; 21 | 22 | int geta(A &ca) 23 | { 24 | return ca.a; 25 | } 26 | 27 | int main() 28 | { 29 | A a(3); 30 | cout< 10 | using namespace std; 11 | 12 | /** 13 | * @brief 定义了一个变量pFun,这个变量是个指针,指向返回值和参数都是空的函数的指针! 14 | */ 15 | void (*pFun)(int); 16 | 17 | /** 18 | * @brief 代表一种新类型,不是变量!所以与上述的pFun不一样! 19 | */ 20 | typedef void (*func)(void); 21 | 22 | void myfunc(void) 23 | { 24 | cout<<"asda"< 2 | #include "inline.h" 3 | 4 | 5 | 6 | using namespace std; 7 | 8 | /** 9 | * @brief inline要起作用,inline要与函数定义放在一起,inline是一种“用于实现的关键字,而不是用于声明的关键字” 10 | * 11 | * @param x 12 | * @param y 13 | * 14 | * @return 15 | */ 16 | int Foo(int x,int y); // 函数声明 17 | inline int Foo(int x,int y) // 函数定义 18 | { 19 | return x+y; 20 | } 21 | 22 | 23 | 24 | // 定义处加inline关键字,推荐这种写法! 25 | inline void A::f1(int x){ 26 | 27 | 28 | } 29 | 30 | 31 | 32 | /** 33 | * @brief 内联能提高函数效率,但并不是所有的函数都定义成内联函数!内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。 34 | * 如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收货会更少!另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。 35 | * 以下情况不宜用内联: 36 | * (1) 如果函数体内的代码比较长,使得内联将导致内存消耗代价比较高。 37 | * (2) 如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。 38 | * 39 | * @return 40 | */ 41 | int main() 42 | { 43 | 44 | 45 | cout< 2 | using namespace std; 3 | class Base 4 | { 5 | public: 6 | inline virtual void who() 7 | { 8 | cout << "I am Base\n"; 9 | } 10 | virtual ~Base() {} 11 | }; 12 | class Derived : public Base 13 | { 14 | public: 15 | inline void who() // 不写inline时隐式内联 16 | { 17 | cout << "I am Derived\n"; 18 | } 19 | }; 20 | 21 | int main() 22 | { 23 | // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。 24 | Base b; 25 | b.who(); 26 | 27 | // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。 28 | Base *ptr = new Derived(); 29 | ptr->who(); 30 | 31 | // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。 32 | delete ptr; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /basic_content/inline/iv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/inline/iv -------------------------------------------------------------------------------- /basic_content/macro/do_while: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/macro/do_while -------------------------------------------------------------------------------- /basic_content/macro/sig_examp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/macro/sig_examp -------------------------------------------------------------------------------- /basic_content/maohao/.README.md.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/maohao/.README.md.un~ -------------------------------------------------------------------------------- /basic_content/maohao/README.md: -------------------------------------------------------------------------------- 1 | # :: 范围解析运算符那些事 2 | 3 | ## 关于作者: 4 | 5 | 个人公众号: 6 | 7 | ![](../img/wechat.jpg) 8 | 9 | - 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间 10 | - 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的 11 | - 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的 12 | 13 | 具体代码见:[maohao.cpp](maohao.cpp) 14 | 15 | -------------------------------------------------------------------------------- /basic_content/maohao/README.md~: -------------------------------------------------------------------------------- 1 | # :: 范围解析运算符那些事 2 | 3 | ## 关于作者: 4 | 5 | 个人公众号: 6 | 7 | ![](../img/wechat.jpg) 8 | 9 | - 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间 10 | - 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的 11 | - 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的 12 | 13 | 具体代码见:[::.cpp](::.cpp) 14 | 15 | -------------------------------------------------------------------------------- /basic_content/maohao/maohao.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int count=0; // 全局(::)的count 5 | 6 | class A { 7 | public: 8 | static int count; // 类A的count (A::count) 9 | 10 | }; 11 | // 静态变量必须在此处定义 12 | int A::count; 13 | int main() { 14 | ::count=1; // 设置全局的count为1 15 | A::count=5; // 设置类A的count为2 16 | cout< 11 | using namespace std; 12 | 13 | class Copyable { 14 | public: 15 | Copyable(){} 16 | Copyable(const Copyable &o) { 17 | cout << "Copied" << endl; 18 | } 19 | }; 20 | Copyable ReturnRvalue() { 21 | return Copyable(); //返回一个临时对象 22 | } 23 | void AcceptVal(Copyable a) { 24 | 25 | } 26 | void AcceptRef(const Copyable& a) { 27 | 28 | } 29 | 30 | int main() { 31 | cout << "pass by value: " << endl; 32 | AcceptVal(ReturnRvalue()); // 应该调用两次拷贝构造函数 33 | cout << "pass by reference: " << endl; 34 | AcceptRef(ReturnRvalue()); //应该只调用一次拷贝构造函数 35 | } 36 | -------------------------------------------------------------------------------- /basic_content/pointer_refer/effec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/pointer_refer/effec -------------------------------------------------------------------------------- /basic_content/pointer_refer/effec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | void test1(int* p) 4 | { 5 | *p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。 6 | return; 7 | } 8 | 9 | void test2(int& p) 10 | { 11 | p = 3; //此处应该首先判断p是否为空,为了测试的需要,此处我们没加。 12 | return; 13 | } 14 | 15 | int main() { 16 | int a=10; 17 | int *p=&a; 18 | test1(p); 19 | test2(a); 20 | cout< 10 | 11 | using namespace std; 12 | 13 | class A{}; 14 | int main() 15 | { 16 | cout< 10 | 11 | 12 | using namespace std; 13 | 14 | class A 15 | { 16 | public: 17 | A(); 18 | ~A(); 19 | static int a; 20 | static void fun3(); 21 | void fun(); 22 | void fun1(); 23 | }; 24 | 25 | int main() 26 | { 27 | cout< 12 | 13 | using namespace std; 14 | 15 | class A 16 | { 17 | public: 18 | char a; 19 | int b; 20 | }; 21 | 22 | /** 23 | * @brief 此时B按照顺序: 24 | * char a 25 | * int b 26 | * short a 27 | * long b 28 | * 根据字节对齐4+4=8+8+8=24 29 | */ 30 | class B:A 31 | { 32 | public: 33 | short a; 34 | long b; 35 | }; 36 | class C 37 | { 38 | A a; 39 | char c; 40 | }; 41 | 42 | class A1 43 | { 44 | virtual void fun(){} 45 | }; 46 | class C1:public A 47 | { 48 | }; 49 | 50 | 51 | int main() 52 | { 53 | cout< 10 | 11 | using namespace std; 12 | 13 | class A 14 | { 15 | public: 16 | char a; 17 | int b; 18 | }; 19 | 20 | class B 21 | { 22 | public: 23 | short a; 24 | long b; 25 | }; 26 | 27 | /** 28 | * @brief 8+16+8=32 29 | */ 30 | class C:A,B 31 | { 32 | char c; 33 | }; 34 | 35 | 36 | int main() 37 | { 38 | cout< 10 | 11 | using namespace std; 12 | 13 | class A{ 14 | 15 | virtual void fun(); 16 | virtual void fun1(); 17 | virtual void fun2(); 18 | virtual void fun3(); 19 | }; 20 | int main() 21 | { 22 | cout< 11 | using namespace std; 12 | class A 13 | { 14 | public: 15 | char b; 16 | virtual void fun() {}; 17 | static int c; 18 | static int d; 19 | static int f; 20 | }; 21 | 22 | 23 | 24 | int main() 25 | { 26 | 27 | /** 28 | * @brief 16 字节对齐、静态变量不影响类的大小、vptr指针=8 29 | */ 30 | cout< 10 | 11 | using namespace std; 12 | 13 | class A 14 | { 15 | virtual void fun() {} 16 | }; 17 | 18 | class B 19 | { 20 | virtual void fun2() {} 21 | }; 22 | class C : virtual public A, virtual public B 23 | { 24 | public: 25 | virtual void fun3() {} 26 | }; 27 | 28 | 29 | int main() 30 | { 31 | 32 | /** 33 | * @brief 8 8 16 派生类虚继承多个虚函数,会继承所有虚函数的vptr 34 | */ 35 | cout< 10 | 11 | using namespace std; 12 | 13 | class A 14 | { 15 | virtual void fun() {} 16 | }; 17 | 18 | class B 19 | { 20 | virtual void fun2() {} 21 | }; 22 | class C : public A, public B 23 | { 24 | public: 25 | virtual void fun3() {} 26 | }; 27 | 28 | 29 | int main() 30 | { 31 | 32 | /** 33 | * @brief 8 8 16 派生类继承多个虚函数,会继承所有虚函数的vptr 34 | */ 35 | cout< 2 | using namespace std; 3 | 4 | class Apple 5 | { 6 | int i; 7 | public: 8 | Apple() 9 | { 10 | i = 0; 11 | cout << "Inside Constructor\n"; 12 | } 13 | ~Apple() 14 | { 15 | cout << "Inside Destructor\n"; 16 | } 17 | }; 18 | 19 | int main() 20 | { 21 | int x = 0; 22 | if (x==0) 23 | { 24 | Apple obj; 25 | } 26 | cout << "End of main\n"; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /basic_content/static/static_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Apple 5 | { 6 | int i; 7 | public: 8 | Apple() 9 | { 10 | i = 0; 11 | cout << "Inside Constructor\n"; 12 | } 13 | ~Apple() 14 | { 15 | cout << "Inside Destructor\n"; 16 | } 17 | }; 18 | 19 | int main() 20 | { 21 | int x = 0; 22 | if (x==0) 23 | { 24 | static Apple obj; 25 | } 26 | cout << "End of main\n"; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /basic_content/static/static_demo.cpp: -------------------------------------------------------------------------------- 1 | // the use of static Static 2 | // variables in a Function 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | void demo() 8 | { 9 | // static variable 10 | static int count = 0; 11 | cout << count << " "; 12 | 13 | // value is updated and 14 | // will be carried to next 15 | // function calls 16 | count++; 17 | } 18 | 19 | int main() 20 | { 21 | for (int i=0; i<5; i++) 22 | demo(); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /basic_content/static/static_error_variable.cpp: -------------------------------------------------------------------------------- 1 | // variables inside a class 2 | 3 | #include 4 | using namespace std; 5 | 6 | class Apple 7 | { 8 | public: 9 | static int i; 10 | 11 | Apple() 12 | { 13 | // Do nothing 14 | }; 15 | }; 16 | 17 | int main() 18 | { 19 | Apple obj1; 20 | Apple obj2; 21 | obj1.i =2; 22 | obj2.i = 3; 23 | 24 | // prints value of i 25 | cout << obj1.i<<" "< 2 | using namespace std; 3 | 4 | class Apple 5 | { 6 | public: 7 | // static member function 8 | static void printMsg() 9 | { 10 | cout<<"Welcome to Apple!"; 11 | } 12 | }; 13 | 14 | // main function 15 | int main() 16 | { 17 | // invoking a static member function 18 | Apple::printMsg(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /basic_content/static/static_variable.cpp: -------------------------------------------------------------------------------- 1 | // variables inside a class 2 | 3 | #include 4 | using namespace std; 5 | 6 | class GfG 7 | { 8 | public: 9 | static int i; 10 | 11 | GfG() 12 | { 13 | // Do nothing 14 | }; 15 | }; 16 | 17 | int GfG::i = 1; 18 | 19 | int main() 20 | { 21 | GfG obj; 22 | // prints value of i 23 | cout << obj.i; 24 | } 25 | -------------------------------------------------------------------------------- /basic_content/struct/ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/struct/ext -------------------------------------------------------------------------------- /basic_content/struct/ext_struct_func.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | struct Base { 5 | int v1; 6 | // private: //error! 7 | int v3; 8 | public: //显示声明public 9 | int v2; 10 | virtual void print(){ 11 | printf("%s\n","Base"); 12 | }; 13 | Base(){cout<<"Base construct"<print(); 31 | delete b; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /basic_content/struct/sf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/struct/sf -------------------------------------------------------------------------------- /basic_content/struct/stff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/struct/stff -------------------------------------------------------------------------------- /basic_content/struct/struct_func: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/struct/struct_func -------------------------------------------------------------------------------- /basic_content/struct/struct_func.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Base { // public 4 | int v1; 5 | // public: //error 6 | int v2; 7 | //private: 8 | int v3; 9 | //void print(){ // c中不能在结构体中嵌入函数 10 | // printf("%s\n","hello world"); 11 | //}; //error! 12 | }; 13 | 14 | void Base(){ 15 | printf("%s\n","I am Base func"); 16 | } 17 | //struct Base base1; //ok 18 | //Base base2; //error 19 | 20 | int main() { 21 | struct Base base; 22 | base.v1=1; 23 | //base.print(); 24 | printf("%d\n",base.v1); 25 | Base(); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /basic_content/struct/struct_func.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Base { 5 | int v1; 6 | // private: //error! 7 | int v3; 8 | public: //显示声明public 9 | int v2; 10 | void print(){ 11 | printf("%s\n","hello world"); 12 | }; 13 | }; 14 | 15 | int main() { 16 | struct Base base1; //ok 17 | Base base2; //ok 18 | Base base; 19 | base.v1=1; 20 | base.v3=2; 21 | base.print(); 22 | printf("%d\n",base.v1); 23 | printf("%d\n",base.v3); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /basic_content/struct/struct_func_func.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Base { 5 | int v1; 6 | // private: //error! 7 | int v3; 8 | public: //显示声明public 9 | int v2; 10 | void print(){ 11 | printf("%s\n","hello world"); 12 | }; 13 | }; 14 | 15 | typedef struct Base1 { 16 | int v1; 17 | // private: //error! 18 | int v3; 19 | public: //显示声明public 20 | int v2; 21 | void print(){ 22 | printf("%s\n","hello world"); 23 | }; 24 | }B; 25 | void Base(){ 26 | printf("%s\n","I am Base func"); 27 | } 28 | //void B() {} //error! 符号 "B" 已经被定义为一个 "struct Base1" 的别名 29 | int main() { 30 | struct Base base; //ok 31 | //Base base1; // error! 32 | base.v1=1; 33 | base.v3=2; 34 | base.print(); 35 | printf("%d\n",base.v1); 36 | printf("%d\n",base.v3); 37 | Base(); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /basic_content/struct/stu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/struct/stu -------------------------------------------------------------------------------- /basic_content/struct_class/README.md: -------------------------------------------------------------------------------- 1 | # struct与class区别 2 | 3 | ## 关于作者: 4 | 5 | 个人公众号: 6 | 7 | ![](../img/wechat.jpg) 8 | 9 | 关于C与C++中struct内容:见[struct那些事](../struct) 10 | 11 | 总的来说,struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。 12 | 13 | 区别: 14 | 15 | 最本质的一个区别就是默认的访问控制 16 | 17 | 默认的继承访问权限。struct 是 public 的,class 是 private 的。 18 | 19 | struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。 20 | -------------------------------------------------------------------------------- /basic_content/this/img/constthis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/this/img/constthis.png -------------------------------------------------------------------------------- /basic_content/this/img/genthis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/this/img/genthis.png -------------------------------------------------------------------------------- /basic_content/this/img/thiscontrust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/this/img/thiscontrust.png -------------------------------------------------------------------------------- /basic_content/this/person: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/this/person -------------------------------------------------------------------------------- /basic_content/this/person.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | using namespace std; 6 | class Person{ 7 | public: 8 | typedef enum { 9 | BOY = 0, 10 | GIRL 11 | }SexType; 12 | Person(char *n, int a,SexType s){ 13 | name=new char[strlen(n)+1]; 14 | strcpy(name,n); 15 | age=a; 16 | sex=s; 17 | } 18 | int get_age() const{ 19 | 20 | return this->age; 21 | } 22 | Person& add_age(int a){ 23 | age+=a; 24 | return *this; 25 | } 26 | ~Person(){ 27 | delete [] name; 28 | } 29 | private: 30 | char * name; 31 | int age; 32 | SexType sex; 33 | }; 34 | 35 | 36 | int main(){ 37 | Person p("zhangsan",20,Person::BOY); 38 | cout< 10 | /** 11 | * 默认访问控制符为public 12 | */ 13 | union UnionTest { 14 | /** 15 | * 可以含有构造函数、析构函数 16 | */ 17 | UnionTest() : i(10) {print(i);}; 18 | ~UnionTest(){}; 19 | int i; 20 | private: 21 | void print(int i){std::cout< 2 | 3 | using namespace std; 4 | 5 | class Base1 { 6 | public: 7 | Base1():value(10) {} 8 | virtual ~Base1() {} 9 | void test1() { cout << "Base test1..." << endl; } 10 | protected: // 保护 11 | int value; 12 | }; 13 | // 默认为私有继承 14 | class Derived1 : Base1 { 15 | public: 16 | void test2() { cout << "value is " << value << endl; } 17 | }; 18 | 19 | class Base { 20 | public: 21 | Base():value(20) {} 22 | virtual ~Base() {} 23 | void test1() { cout << "Base test1..." << endl; } 24 | private: //私有 25 | int value; 26 | }; 27 | 28 | /** 29 | * 子类对父类成员的访问权限跟如何继承没有任何关系, 30 | * “子类可以访问父类的public和protected成员,不可以访问父类的private成员”——这句话对任何一种继承都是成立的。 31 | * 32 | */ 33 | class Derived : Base { 34 | public: 35 | using Base::value; 36 | void test2() { cout << "value is " << value << endl; } 37 | }; 38 | 39 | 40 | int main() 41 | { 42 | Derived1 d1; 43 | d1.test2(); 44 | 45 | Derived d; 46 | d.test2(); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /basic_content/using/using_derived: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/using/using_derived -------------------------------------------------------------------------------- /basic_content/using/using_derived.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file using_derived.cpp 3 | * @brief 函数重装 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-08-07 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Base{ 13 | public: 14 | void f(){ cout<<"f()"< 10 | #define isNs1 1 11 | //#define isGlobal 2 12 | using namespace std; 13 | void func() 14 | { 15 | cout<<"::func"< 11 | #include 12 | using namespace std; 13 | 14 | typedef vector V1; 15 | using V2 = vector; 16 | 17 | 18 | int main() 19 | { 20 | int nums1[] = {1,2,3,4,5,6}; 21 | V1 vec1(nums1,nums1+sizeof(nums1)/sizeof(int)); 22 | int nums2[] = {5,7,6}; 23 | V2 vec2(nums2,nums2+sizeof(nums2)/sizeof(int)); 24 | 25 | for(auto i:vec1) 26 | cout< 11 | using namespace std; 12 | 13 | class Base 14 | { 15 | public: 16 | virtual void fun ( int x = 10 ) 17 | { 18 | cout << "Base::fun(), x = " << x << endl; 19 | } 20 | }; 21 | 22 | class Derived : public Base 23 | { 24 | public: 25 | virtual void fun ( int x=20 ) 26 | { 27 | cout << "Derived::fun(), x = " << x << endl; 28 | } 29 | }; 30 | 31 | 32 | int main() 33 | { 34 | Derived d1; 35 | Base *bp = &d1; 36 | bp->fun(); // 10 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/copy_consrtuct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Base 5 | { 6 | public: 7 | 8 | }; 9 | 10 | class Derived : public Base 11 | { 12 | public: 13 | Derived() 14 | { 15 | cout << "Derived created" << endl; 16 | } 17 | 18 | Derived(const Derived &rhs) 19 | { 20 | cout << "Derived created by deep copy" << endl; 21 | } 22 | 23 | ~Derived() 24 | { 25 | cout << "Derived destroyed" << endl; 26 | } 27 | }; 28 | 29 | int main() 30 | { 31 | Derived s1; 32 | 33 | Derived s2 = s1; // Compiler invokes "copy constructor" 34 | // Type of s1 and s2 are concrete to compiler 35 | 36 | // How can we create Derived1 or Derived2 object 37 | // from pointer (reference) to Base class pointing Derived object? 38 | 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/full_virde.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file full_virde.cpp 3 | * @brief 将基类的析构函数声明为虚函数 4 | * 输出结果: 5 | * Constructing base 6 | * Constructing derived 7 | * Destructing derived 8 | * Destructing base 9 | * @author 光城 10 | * @version v1 11 | * @date 2019-07-24 12 | */ 13 | #include 14 | 15 | using namespace std; 16 | 17 | class base { 18 | public: 19 | base() 20 | { cout<<"Constructing base \n"; } 21 | virtual ~base() 22 | { cout<<"Destructing base \n"; } 23 | }; 24 | 25 | class derived: public base { 26 | public: 27 | derived() 28 | { cout<<"Constructing derived \n"; } 29 | ~derived() 30 | { cout<<"Destructing derived \n"; } 31 | }; 32 | 33 | int main(void) 34 | { 35 | derived *d = new derived(); 36 | base *b = d; 37 | delete b; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/inline_virtual.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class Base 4 | { 5 | public: 6 | inline virtual void who() 7 | { 8 | cout << "I am Base\n"; 9 | } 10 | virtual ~Base() {} 11 | }; 12 | class Derived : public Base 13 | { 14 | public: 15 | inline void who() // 不写inline时隐式内联 16 | { 17 | cout << "I am Derived\n"; 18 | } 19 | }; 20 | 21 | int main() 22 | { 23 | // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。 24 | Base b; 25 | b.who(); 26 | 27 | // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。 28 | Base *ptr = new Derived(); 29 | ptr->who(); 30 | 31 | // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。 32 | delete ptr; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/static_error.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file static_error.cpp 3 | * @brief 静态函数不可以声明为虚函数,同时也不能被const和volatile关键字修饰! 4 | * 原因如下: 5 | * static成员函数不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义 6 | * 虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,静态成员函数没有this指针,所以无法访问vptr。 7 | * @author 光城 8 | * @version v1 9 | * @date 2019-07-24 10 | */ 11 | 12 | virtual static void fun() { } 13 | static void fun() const { } 14 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/vir_de.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file vir_de.cpp 3 | * @brief 派生类的析构函数没有被调用! 4 | * 输出结果: 5 | * Constructing base 6 | * Constructing derived 7 | * Destructing base 8 | * @author 光城 9 | * @version v1 10 | * @date 2019-07-24 11 | */ 12 | 13 | // CPP program without virtual destructor 14 | // causing undefined behavior 15 | #include 16 | 17 | using namespace std; 18 | 19 | class base { 20 | public: 21 | base() 22 | { cout<<"Constructing base \n"; } 23 | ~base() 24 | { cout<<"Destructing base \n"; } 25 | }; 26 | 27 | class derived: public base { 28 | public: 29 | derived() 30 | { cout<<"Constructing derived \n"; } 31 | ~derived() 32 | { cout<<"Destructing derived \n"; } 33 | }; 34 | 35 | int main(void) 36 | { 37 | derived *d = new derived(); 38 | base *b = d; 39 | delete b; 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/virtual_function.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file virtual_function.cpp 3 | * @brief 虚函数可以被私有化,但有一些细节需要注意。 4 | * 基类指针指向继承类对象,则调用继承类对象的函数; 5 | * int main()必须声明为Base类的友元,否则编译失败。 编译器报错: ptr无法访问私有函数。 6 | * 当然,把基类声明为public, 继承类为private,该问题就不存在了。----> 见另外一个例子! 7 | * @author 光城 8 | * @version v1 9 | * @date 2019-07-24 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | class Derived; 16 | 17 | class Base { 18 | private: 19 | virtual void fun() { cout << "Base Fun"; } 20 | friend int main(); 21 | }; 22 | 23 | class Derived: public Base { 24 | public: 25 | void fun() { cout << "Derived Fun"; } 26 | }; 27 | 28 | int main() 29 | { 30 | Base *ptr = new Derived; 31 | ptr->fun(); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/virtual_function1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Derived; 5 | 6 | class Base { 7 | public: 8 | virtual void fun() { cout << "Base Fun"; } 9 | // friend int main(); 10 | }; 11 | 12 | class Derived: public Base { 13 | private: 14 | void fun() { cout << "Derived Fun"; } 15 | }; 16 | 17 | int main() 18 | { 19 | Base *ptr = new Derived; 20 | ptr->fun(); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /basic_content/virtual/set3/virtual_inline.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file virtual_inline.cpp 3 | * @brief 通常类成员函数都会被编译器考虑是否进行内联。 4 | * 但通过基类指针或者引用调用的虚函数必定不能被内联。 5 | * 当然,实体对象调用虚函数或者静态调用时可以被内联,虚析构函数的静态调用也一定会被内联展开。 6 | * @author 光城 7 | * @version v1 8 | * @date 2019-07-24 9 | */ 10 | 11 | #include 12 | using namespace std; 13 | class Base 14 | { 15 | public: 16 | virtual void who() 17 | { 18 | cout << "I am Base\n"; 19 | } 20 | }; 21 | class Derived: public Base 22 | { 23 | public: 24 | void who() 25 | { 26 | cout << "I am Derived\n"; 27 | } 28 | }; 29 | 30 | int main() 31 | { 32 | // note here virtual function who() is called through 33 | // object of the class (it will be resolved at compile 34 | // time) so it can be inlined. 35 | Base b; 36 | b.who(); 37 | 38 | // Here virtual function is called through pointer, 39 | // so it cannot be inlined 40 | Base *ptr = new Derived(); 41 | ptr->who(); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /basic_content/virtual/set4/rtti: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/virtual/set4/rtti -------------------------------------------------------------------------------- /basic_content/virtual/set4/rtti.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file rtti.cpp 3 | * @brief 在面向对象程序设计中,有时我们需要在运行时查询一个对象是否能作为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符类似,C++提供了dynamic_cast函数用于动态转型。相比C风格的强制类型转换和C++ reinterpret_cast,dynamic_cast提供了类型安全检查,是一种基于能力查询(Capability Query)的转换,所以在多态类型间进行转换更提倡采用dynamic_cast 4 | * @author 光城 5 | * @version v1 6 | * @date 2019-07-24 7 | */ 8 | 9 | // CPP program to illustrate 10 | // // Run Time Type Identification 11 | #include 12 | #include 13 | using namespace std; 14 | class B { virtual void fun() {} }; 15 | class D: public B { }; 16 | 17 | int main() 18 | { 19 | B *b = new D; // 向上转型 20 | B &obj = *b; 21 | D *d = dynamic_cast(b); // 向下转型 22 | if(d != NULL) 23 | cout << "works"<(obj); 29 | cout << "works"< 3 | int main(void) 4 | { 5 | const int local = 10; 6 | int *ptr = (int*) &local; 7 | 8 | printf("Initial value of local : %d \n", local); 9 | 10 | *ptr = 100; 11 | 12 | printf("Modified value of local: %d \n", local); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /basic_content/volatile/nv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/volatile/nv -------------------------------------------------------------------------------- /basic_content/volatile/volatile.cpp: -------------------------------------------------------------------------------- 1 | /* Compile code with optimization option */ 2 | #include 3 | 4 | int main(void) 5 | { 6 | const volatile int local = 10; 7 | int *ptr = (int*) &local; 8 | 9 | printf("Initial value of local : %d \n", local); 10 | 11 | *ptr = 100; 12 | 13 | printf("Modified value of local: %d \n", local); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /basic_content/vptr_vtable/img/base.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/basic_content/vptr_vtable/img/base.jpg -------------------------------------------------------------------------------- /c++2.0/c++11/alias.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-3. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | // 不可以对alias template做偏特化或全特化 10 | template 11 | using Vec=vector>; // alias template using新用法 12 | //# define Vec template vector> // 使用宏不行 13 | 14 | int main() { 15 | Vec col; 16 | // 如果使用宏上述会被替换为template vector> error 不是我们想要的 17 | // typedef vector> Vec; // typedef也无法做到,没法指定模板参数 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /c++2.0/c++11/constexpr.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-4. 3 | // 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | // 对于修饰Object来说: 10 | // const并未区分出编译期常量和运行期常量 11 | // constexpr限定在了编译期常量 12 | // constexpr作用:优化!效率! 13 | // constexpr修饰的函数,返回值不一定是编译期常量。It is not a bug, it is a feature. 14 | // const修饰的是类型,constexpr修饰的是用来算出值的那段代码。 15 | /** 16 | * constexpr修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。 17 | * 但是,传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。不 18 | * @param i 19 | * @return 20 | */ 21 | constexpr int foo(int i) 22 | { 23 | return i+10; 24 | } 25 | 26 | int main() 27 | { 28 | int i = 10; 29 | std::array arr; // OK 30 | 31 | foo(i); // Call is Ok 32 | 33 | std::array arr1; // error: the value of ‘i’ is not usable in a constant expression 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /c++2.0/c++11/final.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-3. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | // final关键字用于两个地方 10 | // 第一个用在类,用于说明该类是继承体系下最后的一个类,不要其他类继承我,当继承时就会报错。 11 | class Base final { 12 | public: 13 | Base() {} 14 | 15 | virtual void func() {} 16 | }; 17 | 18 | class Derivered : public Base { // error: cannot derive from ‘final’ base ‘Base’ in derived type ‘Derivered’ 19 | }; 20 | // 第二个用在虚函数,表示这个虚函数不能再被override了,再override就会报错。 21 | class Base1 { 22 | public: 23 | Base1() {} 24 | 25 | virtual void func() final {} 26 | }; 27 | 28 | class Derivered1 : public Base1 { 29 | virtual void func() {} // error: overriding final function ‘virtual void Base1::func()’ 30 | }; 31 | int main() { 32 | 33 | } -------------------------------------------------------------------------------- /c++2.0/c++11/initializer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-3. 3 | // 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int main() { 10 | int i; 11 | int j(); // 0 12 | int *p; 13 | int *q(); // nullptr 14 | 15 | // int x1{5.0}; // error:narrowing conversion 16 | // 编译器调用initializer_list私有构造之前,编译器准备好array(array头)与len,传递给该构造,并没有内含这个array, 17 | // 指针指向array,copy只是浅copy. 18 | // 如今所有容器都接受任意数量的值 insert()或assign() max() min() 19 | 20 | cout< 6 | #include 7 | 8 | using namespace std; 9 | 10 | // noexcepte ()中可以加条件 11 | // 异常可传递 a调用b b抛出异常,a没处理,就会抛出异常 12 | // 1.异常的回传机制:调用foo如果抛出异常,foo会接着往上层抛出异常, 13 | // 如果最上层没有处理,则会调用terminate函数,terminate函数内部调用abort,使程序退出 14 | 15 | 16 | // 2.在使用vector deque等容器的移动构造和移动赋值的时候,如果移动构造和移动赋值没有加上noexcept, 17 | // 则容器增长的时候不会调用move constructor,效率就会偏低,所以后面需要加上noexcept,安心使用。 18 | 19 | void foo() noexcept(true) { 20 | } 21 | 22 | int main() { 23 | foo(); 24 | vector vec; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /c++2.0/c++11/nullptr.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-2. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | void f(int i) { 9 | cout<<"void f(int i)" < 6 | 7 | using namespace std; 8 | 9 | class Base { 10 | public: 11 | Base(){} 12 | virtual void func() {} 13 | }; 14 | class Derivered:public Base{ 15 | virtual void func(int) override {} //error: ‘virtual void Derivered::func(int)’ marked ‘override’, but does not override 16 | }; 17 | // override用于虚函数,上面的virtual void func(int)实际上不是重写父类的虚函数,而是定义一个新的虚函数, 18 | // 我们的本意是重写虚函数,当不加overrride的时候,这样写编译器不会报错, 19 | // 那如果像下面加上override的话,则会报错,表示告诉了编译器,我确实要重写,但写错了,没有重写,于是就报错了, 20 | // 这样就能给我们对虚函数的重写做检查! 21 | 22 | int main() { 23 | 24 | } -------------------------------------------------------------------------------- /c++2.0/c++11/template_template.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-3. 3 | // 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | // template template parameter 模板模板参数 9 | template class Container> 11 | class XCls { 12 | private: 13 | Container c; 14 | }; 15 | 16 | // alias template 17 | template 18 | using Lst = list; 19 | 20 | int main() { 21 | // XCls mylist1; // error 22 | XCls mylist2; 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /c++2.0/c++11/tuple.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-4. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | // tuple使用 11 | int main() { 12 | tuple t, t1, t2; 13 | t = make_tuple(1, 2, "qwe"); 14 | t1 = make_tuple(3, 2, "qwe"); 15 | t2 = make_tuple(3, 2, "qwe"); 16 | int a = get<0>(t); 17 | get<0>(t) = get<1>(t); // 可以修改 18 | cout << a << endl; 19 | cout << (get<0>(t) > get<1>(t) ? "true" : "false") << endl; // 比较大小 20 | cout << (t1 == t2 ? "true" : "false") << endl; 21 | typedef tuple T; 22 | cout << tuple_size::value << endl; // meta programming 处理类型 23 | cout << tuple_size::value << endl; 24 | tuple_element<1, T>::type a1 = 10; 25 | cout << a1 << endl; 26 | return 0; 27 | } -------------------------------------------------------------------------------- /c++2.0/c++11/type_alias.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-3. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | // 第一种使用 11 | // type alias 12 | // 等价于typedef void(*func)(int, int); 13 | using fun=void (*)(int, int); 14 | 15 | void example(int, int) {} 16 | 17 | // 第二种使用 18 | template 19 | struct Container { 20 | using value_type=T; // 等价于typedef T value_type; 21 | }; 22 | 23 | template 24 | void func2(const Cn &cn) { 25 | typename Cn::value_type n; 26 | } 27 | 28 | // 第三种使用 29 | // alias template 30 | template 31 | using string=basic_string>; 32 | // 等价于 typedef basic_string string; 33 | 34 | // 综上:type alias等价于typedef,没有什么不同 35 | // using 的所有用法拓展如下: 36 | // 1.using-directives 37 | // using namespace std; or using std::cout; 38 | // 2. using-declaration 39 | // protected: 40 | // using _Base::_M_alloc; 41 | // 3.c++2.0特性 type alias and alias template 42 | int main() { 43 | fun fn = example; // 函数指针 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /c++2.0/c++11/uniform_initialization.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-2. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int main() { 11 | int value[]{1, 2, 3}; // initializer_list 会关联一个array 里面元素被编译器逐一分解传给函数 12 | vector v{2, 3, 5}; 13 | return 0; 14 | } -------------------------------------------------------------------------------- /c++2.0/c++11/variadic/variadic1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-4. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | // example 1 11 | void printX() { 12 | 13 | } 14 | 15 | // 特化 16 | template 17 | void printX(const T &firstArg, const Type &...args) { 18 | cout << firstArg << endl; // 先减少一个做操作 19 | printX(args...); // 其余的继续分为一个+一包进行递归知道没有了 调用printX() 20 | } 21 | 22 | // 如果写了下面接收任意参数,下面这个跟上面可以共存 泛化版 永远不会被调用,前面特化把它取代了 23 | template 24 | void printX(const Type &...args) { 25 | printX(args...); 26 | } 27 | 28 | 29 | int main() { 30 | printX(1, "hello", bitset<16>(377), 42); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /c++2.0/c++11/variadic/variadic2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-4. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | void print(const char *s) { 10 | while (*s) { 11 | if (*s == '%' && *(++s) != '%') 12 | throw std::runtime_error("invalid format string: missing arguments"); 13 | std::cout << *s++; 14 | } 15 | } 16 | 17 | template 18 | void print(const char *s, T value, Args... args) { 19 | while (*s) { 20 | if (*s == '%' && *(++s) != '%') { 21 | std::cout << value; 22 | print(++s, args...); // 即便当 *s == 0 也会产生调用,以检测更多的类型参数。 23 | return; 24 | } 25 | std::cout << *s++; 26 | } 27 | throw std::logic_error("extra arguments provided to printf"); 28 | } 29 | 30 | int main() { 31 | int *pi = new int; 32 | print("%d %s %p %f\n", 15, "Acc", pi, 3.14); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /c++2.0/c++11/variadic/variadic3_4.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-4. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | // 参数type相同的max 10 | int max(initializer_list initializerList) { 11 | int res = *initializerList.begin(); 12 | for (auto elem:initializerList) 13 | res = max(res, elem); 14 | return res; 15 | } 16 | 17 | 18 | // 参数type相同的maximum 19 | int maximum(int n) { 20 | return n; 21 | } 22 | 23 | template 24 | int maximum(int n, Args...args) { 25 | return std::max(n, maximum(args...)); 26 | } 27 | 28 | int main() { 29 | cout << max({10, 8, 100, 1}) << endl; 30 | cout << maximum(57, 48, 60, 100, 20, 18) << endl; 31 | } -------------------------------------------------------------------------------- /c++2.0/c++11/variadic/variadic5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-4. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // tuple递归调用 12 | 13 | // 得出这种打印[7,5....,42] 14 | // 需要知道有几个以及现在操作的是第几个 sizeof...() 15 | 16 | // cout<< make_tuple(7.5,string("hello"),bitset<16>(377),47); 17 | 18 | 19 | template 20 | struct print_tuple { 21 | static void print(ostream &os, const tuple &t) { 22 | os << get(t) << (IDX + 1 == MAX ? "" : ","); 23 | print_tuple::print(os, t); 24 | } 25 | }; 26 | 27 | // 偏特化 28 | template 29 | struct print_tuple { 30 | static void print(ostream &os, const tuple &t) { 31 | } 32 | }; 33 | 34 | template 35 | ostream &operator<<(ostream &os, const tuple &t) { 36 | os << "["; 37 | print_tuple<0, sizeof...(Args), Args...>::print(os, t); 38 | return os << "]"; 39 | } 40 | 41 | 42 | int main() { 43 | cout << make_tuple(7.5, string("hello"), bitset<16>(377), 47) << endl; 44 | } -------------------------------------------------------------------------------- /codingStyleIdioms/1_classInitializers/1.2_无默认构造的继承.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | #include 5 | class Animal { 6 | public: 7 | Animal(int age) { 8 | std::cout << "Animal(int age) is called" << std::endl; 9 | } 10 | 11 | Animal(const Animal & animal) { 12 | std::cout << "Animal (const Animal &) is called" << std::endl; 13 | } 14 | 15 | Animal &operator=(const Animal & amimal) { 16 | std::cout << "Animal & operator=(const Animal &) is called" << std::endl; 17 | return *this; 18 | } 19 | 20 | ~Animal() { 21 | std::cout << "~Animal() is called" << std::endl; 22 | } 23 | 24 | }; 25 | 26 | class Dog : Animal { 27 | public: 28 | Dog(int age) : Animal(age) { 29 | std::cout << "Dog(int age) is called" << std::endl; 30 | } 31 | 32 | ~Dog() { 33 | std::cout << "~Dog() is called" << std::endl; 34 | } 35 | }; 36 | 37 | int main() { 38 | Animal animal(10); 39 | std::cout << std::endl; 40 | Dog d(100); 41 | std::cout << std::endl; 42 | return 0; 43 | } -------------------------------------------------------------------------------- /codingStyleIdioms/1_classInitializers/1.3_类中const数据成员、引用数据成员.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | 5 | #include 6 | 7 | class Animal { 8 | public: 9 | Animal(int age,std::string name):age_(age),name_(name) { 10 | std::cout << "Animal(int age) is called" << std::endl; 11 | } 12 | private: 13 | int &age_; 14 | const std::string name_; 15 | }; 16 | 17 | int main() { 18 | Animal animal(10,"hh"); 19 | return 0; 20 | } -------------------------------------------------------------------------------- /codingStyleIdioms/1_classInitializers/initializer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | class A { 10 | public: 11 | A(int a) : _a(a), _p(nullptr) { // 初始化列表 12 | 13 | } 14 | 15 | private: 16 | int _a; 17 | int *_p; 18 | }; 19 | 20 | int main() { 21 | A aa(10); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codingStyleIdioms/2_enumclass/namespace.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | // 在创建枚举时,将它们放在名称空间中,以便可以使用有意义的名称访问它们: 9 | namespace EntityType { 10 | enum Enum { 11 | Ground = 0, 12 | Human, 13 | Aerial, 14 | Total 15 | }; 16 | } 17 | 18 | void foo(EntityType::Enum entityType) 19 | { 20 | if (entityType == EntityType::Ground) { 21 | /*code*/ 22 | } 23 | } 24 | 25 | // enum class 26 | enum class EntityType1 { 27 | Ground = 0, 28 | Human, 29 | Aerial, 30 | Total 31 | }; 32 | 33 | void foo(EntityType1 entityType) 34 | { 35 | if (entityType == EntityType1::Ground) { 36 | /*code*/ 37 | } 38 | } 39 | 40 | int main() { 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /codingStyleIdioms/3_RAII/RAII_fstram.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | #include 5 | #include 6 | 7 | // RAII 资源获取即初始化,例2 8 | 9 | // C ++保证在对象超出范围时调用析构函数,而不管控制如何离开该范围。 10 | // 即使抛出异常,所有本地对象也会超出范围,因此它们的相关资源将被清除。 11 | 12 | void foo() { 13 | std::fstream file("bar.txt"); // open a file "bar.txt" 14 | if (rand() % 2) { 15 | // if this exception is thrown, we leave the function, and so 16 | // file's destructor is called, which closes the file handle. 17 | throw std::exception(); 18 | } 19 | // if the exception is not called, we leave the function normally, and so 20 | // again, file's destructor is called, which closes the file handle. 21 | } 22 | 23 | int main() { 24 | try { 25 | foo(); 26 | } catch (std::exception) { 27 | puts("exception!"); 28 | } 29 | } -------------------------------------------------------------------------------- /codingStyleIdioms/3_RAII/c++_example.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-12. 3 | // 4 | #include 5 | int main() { 6 | std::string str = std::string ("toptal"); 7 | std::cout << "string object: " << str << " @ " << &str << "\n"; 8 | 9 | str += ".com"; 10 | std::cout << "string object: " << str << " @ " << &str << "\n"; 11 | 12 | return(0); 13 | } -------------------------------------------------------------------------------- /codingStyleIdioms/3_RAII/c++_example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-12. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | unique_ptr> read_lines_from_file(string &file_name) { 12 | unique_ptr> lines(new vector); 13 | string line; 14 | 15 | ifstream file_handle (file_name.c_str()); 16 | while (file_handle.good() && !file_handle.eof()) { 17 | getline(file_handle, line); 18 | lines->push_back(line); 19 | } 20 | 21 | file_handle.close(); 22 | 23 | return lines; 24 | } 25 | int main() { 26 | // get file name from the first argument 27 | string file_name ("/home/light/CLionProjects/Morden_C++/CMakeLists.txt"); 28 | int count = read_lines_from_file(file_name).get()->size(); 29 | cout << "File " << file_name << " contains " << count << " lines."; 30 | cout< 5 | #include 6 | #include 7 | int main() { 8 | char *str = (char *) malloc(7); 9 | strcpy(str, "toptal"); 10 | printf("char array = \"%s\" @ %u\n", str, str); 11 | 12 | str = (char *) realloc(str, 11); 13 | strcat(str, ".com"); 14 | printf("char array = \"%s\" @ %u\n", str, str); 15 | 16 | free(str); 17 | 18 | return(0); 19 | } -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/.a.cpp.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/codingStyleIdioms/5_pImpl/.a.cpp.un~ -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/.pimplTime.cpp.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/codingStyleIdioms/5_pImpl/.pimplTime.cpp.un~ -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/.timePimpl.cpp.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/codingStyleIdioms/5_pImpl/.timePimpl.cpp.un~ -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/README.md: -------------------------------------------------------------------------------- 1 | # C++惯用法之pImpl 2 | 3 | “指向实现的指针”或“pImpl”是一种 C++ 编程技巧,它将类的实现细节从对象表示中移除,放到一个分离的类中,并以一个不透明的指针进行访问。 4 | 5 | 使用pImpl惯用法的原因如下: 6 | 7 | 考虑如下例子: 8 | 9 | ```cpp 10 | class X 11 | { 12 | private: 13 | C c; 14 | D d; 15 | } ; 16 | ``` 17 | 18 | 变成pImpl就是下面这样子 19 | 20 | ```cpp 21 | class X 22 | { 23 | private: 24 | struct XImpl; 25 | XImpl* pImpl; 26 | }; 27 | ``` 28 | 29 | CPP定义: 30 | 31 | ```cpp 32 | struct X::XImpl 33 | { 34 | C c; 35 | D d; 36 | }; 37 | ``` 38 | 39 | - 二进制兼容性 40 | 41 | 开发库时,可以在不破坏与客户端的二进制兼容性的情况下向XImpl添加/修改字段(这将导致崩溃!)。 由于在向Ximpl类添加新字段时X类的二进制布局不会更改,因此可以安全地在次要版本更新中向库添加新功能。 42 | 43 | 当然,您也可以在不破坏二进制兼容性的情况下向X / XImpl添加新的公共/私有非虚拟方法,但这与标准的标头/实现技术相当。 44 | 45 | - 数据隐藏 46 | 47 | 如果您正在开发一个库,尤其是专有库,则可能不希望公开用于实现库公共接口的其他库/实现技术。 要么是由于知识产权问题,要么是因为您认为用户可能会被诱使对实现进行危险的假设,或者只是通过使用可怕的转换技巧来破坏封装。 PIMPL解决/缓解了这一难题。 48 | 49 | - 编译时间 50 | 51 | 编译时间减少了,因为当您向XImpl类添加/删除字段和/或方法时(仅映射到标准技术中添加私有字段/方法的情况),仅需要重建X的源(实现)文件。 实际上,这是一种常见的操作。 52 | 53 | 使用标准的标头/实现技术(没有PIMPL),当您向X添加新字段时,曾经重新分配X(在堆栈或堆上)的每个客户端都需要重新编译,因为它必须调整分配的大小 。 好吧,每个从未分配X的客户端也都需要重新编译,但这只是开销(客户端上的结果代码是相同的)。 54 | 55 | 56 | 57 | > https://stackoverflow.com/questions/8972588/is-the-pimpl-idiom-really-used-in-practices -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/a.cpp~: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class C { 5 | 6 | public: 7 | virtual void print(); 8 | }; 9 | 10 | 11 | class CC:public C { 12 | public: 13 | void print() { 14 | cout<<"CC"<(new C); 21 | //c->print(); 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/noPimpl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class C { 6 | vector v; 7 | string s; 8 | }; 9 | class D { 10 | string s; 11 | }; 12 | 13 | class X { 14 | private: 15 | C c; 16 | D d; 17 | }; 18 | 19 | 20 | int main() { 21 | 22 | X x; 23 | } 24 | -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/pimpl.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | // pImpl: Pointer-to-Implementation 9 | 10 | class private_foo; 11 | class foo { 12 | public: 13 | foo(); 14 | 15 | ~foo(); 16 | 17 | void bar(); 18 | 19 | private: 20 | private_foo *pImpl; 21 | }; 22 | 23 | class private_foo { 24 | public: 25 | void bar() { 26 | cout<<"private_foo invoke bar funciton."<bar(); 42 | } 43 | 44 | 45 | int main() { 46 | foo f; 47 | f.bar(); 48 | } -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/pimplTime.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class C { 6 | vector v; 7 | string s; 8 | }; 9 | class D { 10 | string s; 11 | }; 12 | 13 | class X { 14 | private: 15 | struct XImpl; 16 | XImpl* pImpl; 17 | }; 18 | 19 | struct X::XImpl { 20 | C c; 21 | D d; 22 | }; 23 | 24 | int main() { 25 | X x; 26 | } 27 | -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/pimplTime.cpp~: -------------------------------------------------------------------------------- 1 | #include "pimplTime.h" 2 | 3 | struct X::XImpl { 4 | C c; 5 | D d; 6 | } 7 | 8 | int main() { 9 | X x; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/pimplTime.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class C { 6 | vector v; 7 | string s; 8 | }; 9 | class D { 10 | string s; 11 | }; 12 | 13 | class X { 14 | private: 15 | struct XImpl; 16 | XImpl* pImpl; 17 | }; 18 | 19 | 20 | -------------------------------------------------------------------------------- /codingStyleIdioms/5_pImpl/timePimpl.cpp~: -------------------------------------------------------------------------------- 1 | #include <> 2 | -------------------------------------------------------------------------------- /codingStyleIdioms/README.md: -------------------------------------------------------------------------------- 1 | # 你最喜欢的c++编程风格惯用法是什么? 2 | 3 | 在stackoverflow上找到了一篇文章,写的蛮好的,地址如下: 4 | 5 | > https://stackoverflow.com/questions/276173/what-are-your-favorite-c-coding-style-idioms#comment60171463_2034439 6 | 7 | 由于是英文的,且比较重要,于是总结成下面几条! 8 | 9 | - [1.类初始化列表](./1_classInitializers) 10 | - [2.枚举类替换命名空间](./2_enumclass_namespace) 11 | - [3.RAII(资源获取即初始化)](./3_RAII) 12 | - [4.copy and swap](./4_copy-swap) 13 | - [5.pImpl(指针指向具体实现)](./5_pImpl) 14 | 15 | -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/.idea/Threading_In_CPlusPlus.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/1.thread/intro.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std::chrono; 9 | using namespace std; 10 | 11 | using ull = unsigned long long; 12 | ull OddSum = 0; 13 | ull EvenSum = 0; 14 | 15 | void findEven(ull start, ull end) { 16 | for (ull i = start; i <= end; ++i) 17 | if ((i & 1) == 0) 18 | EvenSum += i; 19 | } 20 | 21 | void findOdd(ull start, ull end) { 22 | for (ull i = start; i <= end; ++i) 23 | if ((i & 1) == 1) 24 | OddSum += i; 25 | } 26 | 27 | int main() { 28 | 29 | ull start = 0, end = 1900000000; 30 | 31 | auto startTime = high_resolution_clock::now(); 32 | findOdd(start, end); 33 | findEven(start, end); 34 | auto stopTime = high_resolution_clock::now(); 35 | auto duration = duration_cast(stopTime - startTime); 36 | 37 | cout << "OddSum : " << OddSum << endl; 38 | cout << "EvenSum: " << EvenSum << endl; 39 | cout << "Sec: " << duration.count() / 1000000 << endl; 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/2.create_type/1.function_pointer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | // 1.函数指针 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | void fun(int x) { 12 | while (x-- > 0) { 13 | cout << x << endl; 14 | } 15 | } 16 | // 注意:如果我们创建多线程 并不会保证哪一个先开始 17 | int main() { 18 | std::thread t1(fun, 10); 19 | // std::1.thread t2(fun, 10); 20 | t1.join(); 21 | // t2.join(); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/2.create_type/2.lambda_function.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | // 1.函数指针 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // 注意:如果我们创建多线程 并不会保证哪一个先开始 12 | int main() { 13 | // 2.Lambda函数 14 | auto fun = [](int x) { 15 | while (x-- > 0) { 16 | cout << x << endl; 17 | } 18 | }; 19 | // std::1.thread t1(fun, 10); 20 | // 也可以写成下面: 21 | std::thread t1_1([](int x) { 22 | while (x-- > 0) { 23 | cout << x << endl; 24 | } 25 | }, 11); 26 | // std::1.thread t2(fun, 10); 27 | // t1.join(); 28 | t1_1.join(); 29 | // t2.join(); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/2.create_type/3.functor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // 3.functor (Funciton Object) 12 | class Base { 13 | public: 14 | void operator()(int x) { 15 | while (x-- > 0) { 16 | cout << x << endl; 17 | } 18 | } 19 | }; 20 | 21 | int main() { 22 | thread t(Base(), 10); 23 | t.join(); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/2.create_type/4.no_static_member_function.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // 4.Non-static member function 12 | class Base { 13 | public: 14 | void fun(int x) { 15 | while (x-- > 0) { 16 | cout << x << endl; 17 | } 18 | } 19 | }; 20 | 21 | int main() { 22 | Base b; 23 | thread t(&Base::fun,&b, 10); 24 | t.join(); 25 | return 0; 26 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/2.create_type/5.static_member_function.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // 4.Non-static member function 12 | class Base { 13 | public: 14 | static void fun(int x) { 15 | while (x-- > 0) { 16 | cout << x << endl; 17 | } 18 | } 19 | }; 20 | 21 | int main() { 22 | thread t(&Base::fun, 10); 23 | t.join(); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/3.join_detach/detach.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | // join 注意点 6 | 7 | /** 8 | * 这用于从父线程分离新创建的线程 9 | * 在分离线程之前,请务必检查它是否可以joinable, 10 | * 否则可能会导致两次分离,并且双重detach()将导致程序终止 11 | * 如果我们有分离的线程并且main函数正在返回,那么分离的线程执行将被挂起 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | using namespace std; 18 | 19 | void run(int count) { 20 | while (count-- > 0) { 21 | cout << count << endl; 22 | } 23 | std::this_thread::sleep_for(chrono::seconds(3)); 24 | } 25 | 26 | int main() { 27 | thread t1(run, 10); 28 | cout << "main()" << endl; 29 | t1.detach(); 30 | if(t1.joinable()) 31 | t1.detach(); 32 | cout << "main() after" << endl; 33 | return 0; 34 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/3.join_detach/join.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-31. 3 | // 4 | 5 | // join 注意点 6 | 7 | /** 8 | * 一旦线程开始,我们要想等待线程完成,需要在该对象上调用join() 9 | * 双重join将导致程序终止 10 | * 在join之前我们应该检查显示是否可以被join,通过使用joinable() 11 | */ 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | 19 | void run(int count) { 20 | while (count-- > 0) { 21 | cout << count << endl; 22 | } 23 | std::this_thread::sleep_for(chrono::seconds(3)); 24 | } 25 | 26 | int main() { 27 | thread t1(run, 10); 28 | cout << "main()" << endl; 29 | t1.join(); 30 | if (t1.joinable()) { 31 | t1.join(); 32 | } 33 | cout << "main() after" << endl; 34 | return 0; 35 | } -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/4.mutex/critical_section.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-1. 3 | // 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int sum = 0; //shared 11 | 12 | mutex m; 13 | 14 | void *countgold() { 15 | int i; //local to each thread 16 | for (i = 0; i < 10000000; i++) { 17 | m.lock(); 18 | sum += 1; 19 | m.unlock(); 20 | } 21 | return NULL; 22 | } 23 | 24 | int main() { 25 | thread t1(countgold); 26 | thread t2(countgold); 27 | 28 | //Wait for both threads to finish 29 | t1.join(); 30 | t2.join(); 31 | 32 | cout << "sum = " << sum << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /concurrency/Threading_In_CPlusPlus/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(Threading_In_CPlusPlus) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") 6 | 7 | add_executable(intro 1.thread/intro.cpp) 8 | add_executable(1.thread 1.thread/thread.cpp) 9 | add_executable(1.function_pointer 2.create_type/1.function_pointer.cpp) 10 | add_executable(2.lambda_function 2.create_type/2.lambda_function.cpp) 11 | add_executable(3.functor 2.create_type/3.functor.cpp) 12 | add_executable(4.static_member_function 2.create_type/4.no_static_member_function.cpp) 13 | add_executable(5.static_member_function 2.create_type/5.static_member_function.cpp) 14 | add_executable(join 3.join_detach/join.cpp) 15 | add_executable(detach 3.join_detach/detach.cpp) 16 | add_executable(critical_section 4.mutex/critical_section.cpp) -------------------------------------------------------------------------------- /concurrency/concurrency_v1/chapter1/1_helloworld.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-5. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | void hello() { 12 | cout << "hello world" << endl; 13 | } 14 | 15 | int main() { 16 | thread t(hello); 17 | t.join(); // must add this line otherwise will failed! 18 | // 需要注意的是线程对象执行了join后就不再joinable了,所以只能调用join一次。 19 | return 0; 20 | } -------------------------------------------------------------------------------- /concurrency/concurrency_v1/chapter2/2.2_transfer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-5. 3 | // 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class X { 10 | public: 11 | void do_length_work() {}; 12 | }; 13 | 14 | void process_big_object(std::unique_ptr); 15 | 16 | int main() { 17 | X my_x; 18 | thread t(&X::do_length_work, &my_x); // 1 19 | 20 | 21 | std::unique_ptr p(new X); 22 | p->do_length_work(); 23 | std::thread tt(process_big_object,std::move(p)); 24 | //std::thread实例的可移动且不可复制性。不可复制保性证了在同一时间点, 25 | // 一个std::thread实例只能关联一个执行线程;可移动性使得程序员可以自己决定,哪个实例拥有实际执行线程的所有权。 26 | return 0; 27 | } -------------------------------------------------------------------------------- /concurrency/concurrency_v1/chapter2/2_5_id.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-11-5. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | 11 | // 线程的通用标识符 12 | std::thread::id master_thread; 13 | 14 | void do_master_thread_work() { 15 | cout << "master" << endl; 16 | } 17 | 18 | void do_common_work() { 19 | cout << "common" << endl; 20 | } 21 | 22 | void some_core_part_of_algorithm() { 23 | if (std::this_thread::get_id() == master_thread) { 24 | do_master_thread_work(); 25 | } 26 | do_common_work(); 27 | } 28 | 29 | int main() { 30 | std::cout << std::this_thread::get_id() << endl; 31 | thread t(some_core_part_of_algorithm); 32 | t.join(); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /design_pattern/singleton/barrier_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | #include 5 | 6 | using namespace std; 7 | 8 | #include 9 | 10 | #define barrier() __asm__ volatile ("lwsync") 11 | 12 | // method 1 operator new + placement new 13 | //singleton *instance() { 14 | // if (p == nullptr) { 15 | // lock_guard guard(lock_); 16 | // if (p == nullptr) { 17 | // singleton *tmp = static_cast(operator new(sizeof(singleton))); 18 | // new(p)singleton(); 19 | // p = tmp; 20 | // } 21 | // } 22 | // return p; 23 | //} 24 | class singleton { 25 | private: 26 | singleton() {} 27 | 28 | static singleton *p; 29 | static mutex lock_; 30 | public: 31 | static singleton *instance(); 32 | }; 33 | 34 | singleton *singleton::p = nullptr; 35 | 36 | singleton *singleton::instance() { 37 | if (p == nullptr) { 38 | lock_guard guard(lock_); 39 | barrier(); 40 | if (p == nullptr) { 41 | p = new singleton(); 42 | } 43 | } 44 | return p; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /design_pattern/singleton/cpulpuls11_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | #include 10 | #include 11 | 12 | //C++ 11版本之后的跨平台实现 13 | class singleton { 14 | private: 15 | singleton() {} 16 | 17 | static mutex lock_; 18 | static atomic p; 19 | public: 20 | singleton *instance(); 21 | }; 22 | 23 | mutex singleton::lock_; 24 | atomic singleton::p; 25 | 26 | /* 27 | * std::atomic_thread_fence(std::memory_order_acquire); 28 | * std::atomic_thread_fence(std::memory_order_release); 29 | * 这两句话可以保证他们之间的语句不会发生乱序执行。 30 | */ 31 | singleton *singleton::instance() { 32 | singleton *tmp = p.load(memory_order_relaxed); 33 | atomic_thread_fence(memory_order_acquire); 34 | if (tmp == nullptr) { 35 | lock_guard guard(lock_); 36 | tmp = p.load(memory_order_relaxed); 37 | if (tmp == nullptr) { 38 | tmp = new singleton(); 39 | atomic_thread_fence(memory_order_release); 40 | p.store(tmp, memory_order_relaxed); 41 | } 42 | } 43 | return p; 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /design_pattern/singleton/dcl_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | #include 5 | 6 | using namespace std; 7 | 8 | #include 9 | 10 | class singleton { 11 | private: 12 | singleton() {} 13 | 14 | static singleton *p; 15 | static mutex lock_; 16 | public: 17 | singleton *instance(); 18 | 19 | // 实现一个内嵌垃圾回收类 20 | class CGarbo 21 | { 22 | public: 23 | ~CGarbo() 24 | { 25 | if(singleton::p) 26 | delete singleton::p; 27 | } 28 | }; 29 | static CGarbo Garbo; // 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象 30 | }; 31 | 32 | singleton *singleton::p = nullptr; 33 | singleton::CGarbo Garbo; 34 | 35 | singleton* singleton::instance() { 36 | if (p == nullptr) { 37 | lock_guard guard(lock_); 38 | if (p == nullptr) 39 | p = new singleton(); 40 | } 41 | return p; 42 | } 43 | -------------------------------------------------------------------------------- /design_pattern/singleton/hungrysingleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-6. 3 | // 4 | 5 | class singleton { 6 | private: 7 | singleton() {} 8 | static singleton *p; 9 | public: 10 | static singleton *instance(); 11 | }; 12 | 13 | singleton *singleton::p = new singleton(); 14 | singleton* singleton::instance() { 15 | return p; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /design_pattern/singleton/iazysingleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-6. 3 | // 4 | 5 | class singleton { 6 | private: 7 | singleton() {} 8 | static singleton *p; 9 | public: 10 | static singleton *instance(); 11 | }; 12 | 13 | singleton *singleton::p = nullptr; 14 | 15 | singleton* singleton::instance() { 16 | if (p == nullptr) 17 | p = new singleton(); 18 | return p; 19 | } 20 | -------------------------------------------------------------------------------- /design_pattern/singleton/lock_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | 9 | class singleton { 10 | private: 11 | singleton() {} 12 | static singleton *p; 13 | static mutex lock_; 14 | public: 15 | static singleton *instance(); 16 | }; 17 | 18 | singleton *singleton::p = nullptr; 19 | 20 | singleton* singleton::instance() { 21 | lock_guard guard(lock_); 22 | if (p == nullptr) 23 | p = new singleton(); 24 | return p; 25 | } 26 | -------------------------------------------------------------------------------- /design_pattern/singleton/pthreadoncesingleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-6. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | class singleton { 9 | private: 10 | singleton(); //私有构造函数,不允许使用者自己生成对象 11 | singleton(const singleton &other); 12 | 13 | //要写成静态方法的原因:类成员函数隐含传递this指针(第一个参数) 14 | static void init() { 15 | p = new singleton(); 16 | } 17 | 18 | static pthread_once_t ponce_; 19 | static singleton *p; //静态成员变量 20 | public: 21 | singleton *instance() { 22 | // init函数只会执行一次 23 | pthread_once(&ponce_, &singleton::init); 24 | return p; 25 | } 26 | }; 27 | 28 | 29 | -------------------------------------------------------------------------------- /design_pattern/singleton/static_local_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | class singleton { 10 | private: 11 | static singleton *p; 12 | singleton() {} 13 | public: 14 | singleton *instance(); 15 | }; 16 | 17 | singleton *singleton::instance() { 18 | static singleton p; 19 | return &p; 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /effective_c++/2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-9-11. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | struct A { 9 | #define p "hello" 10 | }; 11 | 12 | class C { 13 | public: 14 | // static const 可以直接在类内部初始化 15 | // no-const static 只能在外面初始化 16 | static const int NUM = 3; //声明 17 | enum con { 18 | NUM1 = 3 19 | }; 20 | }; 21 | 22 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 23 | template 24 | inline int Max(const T& a, const T& b){ 25 | return (a>b ? a:b); 26 | } 27 | const int C::NUM; // 定义 28 | int main() { 29 | cout << p << endl; // macro is global 30 | C c; 31 | cout << &c.NUM << endl; // 未定义的引用,需要定义 32 | 33 | cout << C::NUM1 << endl; 34 | // cout << &C:NUM1 << endl; //error enum no address 35 | 36 | int a=5, b=0; 37 | cout< 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int epfd, nfds; 8 | char buf[256]; 9 | struct epoll_event event, events[5]; 10 | epfd = epoll_create(1); 11 | event.data.fd = STDIN_FILENO; 12 | event.events = EPOLLIN; // LT是默认模式 13 | epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event); 14 | while (1) { 15 | nfds = epoll_wait(epfd, events, 5, -1); 16 | int i; 17 | for (i = 0; i < nfds; ++i) { 18 | if (events[i].data.fd == STDIN_FILENO) { 19 | // LT模式,如果数据读完了,则下次调用epoll_wait会被阻塞,读事件不被触发 20 | read(STDIN_FILENO, buf, sizeof(buf)); 21 | printf("hello world\n"); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /epoll/test_epoll3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * 实验3使用ET模式,但是每次读就绪后都主动对描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件,由上面的描述我们可以知道,会 7 | * 再次触发读就绪,这样就导致程序出现死循环,不断地在屏幕中输出”hello world”。但是,如果我们将EPOLL_CTL_MOD 改 8 | * 为EPOLL_CTL_ADD,则程序的运行将不会出现死循环的情况。 9 | * 10 | */ 11 | 12 | int main() 13 | { 14 | int epfd, nfds; 15 | struct epoll_event event, events[5]; 16 | epfd = epoll_create(1); 17 | event.data.fd = STDIN_FILENO; 18 | event.events = EPOLLIN | EPOLLET; 19 | epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event); 20 | while (1) { 21 | nfds = epoll_wait(epfd, events, 5, -1); 22 | int i; 23 | for (i = 0; i < nfds; ++i) { 24 | if (events[i].data.fd == STDIN_FILENO) { 25 | printf("hello world\n"); 26 | event.data.fd = STDIN_FILENO; 27 | event.events = EPOLLIN | EPOLLET; 28 | epoll_ctl(epfd, EPOLL_CTL_MOD, STDIN_FILENO, &event); // 主动修改事件属性 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /img/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/img/wechat.jpg -------------------------------------------------------------------------------- /ipc/README.md: -------------------------------------------------------------------------------- 1 | 参考自https://github.com/fanflame/cplusplus_ipc.git -------------------------------------------------------------------------------- /ipc/named_pipe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // 7 | // Created by fanqiang on 2020/3/12. 8 | // 有名管道 9 | // 在文件系统中存在文件节点:管道文件 10 | // 该文件不占磁盘空间 11 | // 调用mkfifo之后,内核会在用户空间生成一个文件名 12 | // 在调用open之后会在内核中创建管道 13 | // 可以实现无亲缘关系进程间通信 14 | 15 | 16 | //要测试该例子,需要线运行该main,生成可执行文件之后,运行named_pipe_another.cpp,然后查看输出; 17 | // 18 | using namespace std; 19 | 20 | 21 | int main() { 22 | int ret = mkfifo("./namedpipe10", 0777);// 第一个参数标示文件名; 23 | // 会在当前目录下创建一个namedpipe的管道文件;umask是0777(8进制的 777) 24 | // 如果不是8进制下的0777,打开管道文件会失败 25 | if (ret == -1) { 26 | cout << "有名管道创建失败" << endl; 27 | // return -1; 28 | } 29 | cout << "有名管道创建成功" << endl; 30 | 31 | int open_fd = open("./namedpipe10", O_WRONLY);//第二个参数标示只写 32 | if (open_fd == -1) { 33 | cout << "有名管道打开失败" << endl; 34 | return -1; 35 | } 36 | cout << "有名管道打开成功" << endl; 37 | string content = "from another progress"; 38 | write(open_fd,content.data(),content.size()); 39 | while(1); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /ipc/named_pipe_another.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // 7 | // Created by fanqiang on 2020/3/12. 8 | // 有名管道 9 | // 在文件系统中存在文件节点:管道文件 10 | // 该文件不占磁盘空间 11 | // 调用mkfifo之后,内核会在用户空间生成一个文件名 12 | // 在调用open之后会在内核中创建管道 13 | // 可以实现无亲缘关系进程间通信 14 | // 15 | using namespace std; 16 | 17 | int main() { 18 | int fd = open("./namedpipe10"/*文件名与pipe_name中创建的管道文件一直*/, O_RDONLY); 19 | if (fd == -1) { 20 | cout << "管道文件打开失败" << endl; 21 | return -1; 22 | } 23 | cout << "管道文件打开成功" << endl; 24 | int size = 200; 25 | char *rec = new char[size](); 26 | read(fd, rec, size); 27 | cout << "read from anther progress:" << rec << endl; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /ipc/signal.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fanqiang on 2020/3/12. 3 | // 使用内核中已经存在的信号对象 4 | // kill -l查看内核中支持多少种信号 5 | // 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | void myfun(int signum) { 13 | cout << "myfun:signum" << signum << endl; 14 | int i = 0; 15 | while (i < 6) { 16 | i++; 17 | sleep(1); 18 | cout << "myfun:i:" << i << endl; 19 | } 20 | } 21 | 22 | int main() { 23 | // kill(pid,9/*信号*/); 24 | signal(SIGALRM, myfun);//接收到14的信号后,执行myfun 25 | // signal(14, SIG_IGN);//接收到14的信号后,忽略 26 | // signal(14, SIG_DFL);//接收到14的信号后,安装默认方式处理 27 | cout << "before" << endl; 28 | alarm(5);//10s之后终止当前进程 29 | cout << "after" << endl; 30 | int i = 0; 31 | while (i < 20) { 32 | i++; 33 | sleep(1); 34 | cout << "main:i:" << i << endl; 35 | } 36 | return 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/.CMakeLists.txt.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/learn_class/modern_C++_30/.CMakeLists.txt.un~ -------------------------------------------------------------------------------- /learn_class/modern_C++_30/RAII/heap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class bar { 6 | 7 | }; 8 | 9 | // java 程序员风格 10 | void foo() { 11 | cout << "method 1" << endl; 12 | bar *ptr = new bar(); 13 | delete ptr; 14 | } 15 | 16 | bar *make_bar() { 17 | bar *ptr = nullptr; 18 | try { 19 | ptr = new bar(); 20 | } catch (...) { 21 | delete ptr; 22 | throw; 23 | } 24 | return ptr; 25 | } 26 | // 独立出函数 分配和释放不在一个函数里 27 | void foo1() { 28 | cout << "method 2" << endl; 29 | bar *ptr = make_bar(); 30 | delete ptr; 31 | } 32 | 33 | 34 | int main() { 35 | foo(); 36 | foo1(); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/RAII/stack.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-9. 3 | // 4 | #include 5 | class Obj { 6 | public: 7 | Obj() { puts("Obj()"); } 8 | ~Obj() { puts("~Obj()"); } 9 | }; 10 | void foo(int n) 11 | { 12 | Obj obj; 13 | if (n == 42) 14 | throw "life, the universe and everything"; 15 | } 16 | // 不管是否发生了异常,obj 的析构函数都会得到执行。 17 | int main() 18 | { 19 | try { 20 | foo(41); 21 | foo(42); 22 | } 23 | catch (const char* s) { 24 | puts(s); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/README.md: -------------------------------------------------------------------------------- 1 | 学习自:https://jguegant.github.io/blogs/tech/sfinae-introduction.html 2 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/SFINAE.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-5. 3 | // 4 | #include 5 | 6 | using namespace std; 7 | 8 | template 9 | class IsClassT { 10 | private: 11 | typedef char One; 12 | typedef struct { 13 | char a[2]; 14 | } Two; 15 | 16 | template 17 | static One test(int C::*); 18 | 19 | // Will be chosen if T is anything except a class. 20 | template 21 | static Two test(...); 22 | 23 | public: 24 | enum { 25 | Yes = sizeof(IsClassT::test(0)) == 1 26 | }; 27 | enum { 28 | No = !Yes 29 | }; 30 | }; 31 | 32 | struct A { 33 | }; 34 | 35 | int main() { 36 | // 0不能转换为int int::*因为int不是类,所以它不能有成员指针。 37 | cout << IsClassT::Yes << endl; 38 | cout << IsClassT::Yes << endl; 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/SFINAE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/learn_class/modern_C++_30/SFINAE/SFINAE.pdf -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/auto.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | #include 5 | 6 | bool f(); 7 | 8 | auto test = f(); // Famous usage, auto deduced that test is a boolean, hurray! 9 | 10 | 11 | 12 | // vvv t wasn't declare at that point, it will be after as a parameter! 13 | template 14 | decltype(t.serialize()) g(const T &t) {} // Compilation error 15 | 16 | // Less famous usage: 17 | // vvv auto delayed the return type specification! 18 | // vvv vvv the return type is specified here and use t! 19 | template 20 | auto g(const T &t) -> decltype(t.serialize()) {} // No compilation error. 21 | 22 | 23 | auto myFunction() // Automagically figures out that myFunction returns ints. 24 | { 25 | return int(); 26 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/blending2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | 5 | #include 6 | #include "structData.h" 7 | 8 | 9 | template 10 | struct hasSerialize : std::false_type { 11 | 12 | }; 13 | template 14 | struct hasSerialize().serialize())> : std::true_type { 15 | 16 | }; 17 | 18 | template 19 | std::string serialize(const T &obj) { 20 | // 不加constexpr 报错:error: no member named 'serialize' in 'A'. 21 | if constexpr (hasSerialize::value) // c++17特性 22 | return obj.serialize(); 23 | else 24 | return to_string(obj); 25 | } 26 | 27 | int main() { 28 | A a; 29 | B b; 30 | C c; 31 | 32 | // The following lines work like a charm! 33 | std::cout << serialize(a) << std::endl; 34 | std::cout << serialize(b) << std::endl; 35 | std::cout << serialize(c) << std::endl; 36 | 37 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/constexpr.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | #include 5 | 6 | constexpr int factorial(int n) { 7 | return n <= 1 ? 1 : (n * factorial(n - 1)); 8 | } 9 | 10 | struct testStruct : std::true_type { 11 | }; // Inherit from the true type. 12 | 13 | int main() { 14 | int i = factorial(5); // Call to a constexpr function. 15 | // Will be replace by a good compiler by: 16 | // int i = 120; 17 | std::cout << i << std::endl; 18 | 19 | 20 | constexpr bool testVar = testStruct(); // Generate a compile-time testStruct. 21 | bool test = testStruct::value; // Equivalent to: test = true; 22 | std::cout << test << std::endl; 23 | test = testVar; // true_type has a constexpr converter operator, equivalent to: test = true; 24 | std::cout << test << std::endl; 25 | } 26 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/decltype.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | #include 5 | struct Default { 6 | int foo() const {return 1;} 7 | }; 8 | 9 | struct NonDefault { 10 | NonDefault(const NonDefault&) {} 11 | int foo() const {return 1;} 12 | }; 13 | 14 | int main() 15 | { 16 | decltype(Default().foo()) n1 = 1; // int n1 17 | // decltype(NonDefault().foo()) n2 = n1; // error: no default constructor 18 | decltype(std::declval().foo()) n2 = n1; // int n2 19 | std::cout << "n2 = " << n2 << '\n'; 20 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/hana.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | // https://www.boost.org/doc/libs/1_62_0/libs/hana/doc/html/structboost_1_1hana_1_1type.html#a2d2e7e08e284f7e0bd1bd9c3ad0e0a2b 5 | #include 6 | #include 7 | #include 8 | 9 | namespace hana = boost::hana; 10 | 11 | 12 | int main() { 13 | // 检查成员 14 | struct Person { 15 | std::string name; 16 | }; 17 | auto has_name = hana::is_valid([](auto &&p) -> decltype(p.name) {}); 18 | 19 | Person joe{"Joe"}; 20 | static_assert(has_name(joe), ""); 21 | static_assert(!has_name(1), ""); 22 | // 检查嵌套类型 23 | auto has_value_type = hana::is_valid([](auto t) -> hana::type {}); 24 | static_assert(has_value_type(hana::type_c>), ""); 25 | static_assert(!has_value_type(hana::type_c), ""); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/overload1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | #include 5 | 6 | void f(std::string s); // int can't be convert into a string. 7 | void f(double d); // int can be implicitly convert into a double, so this version could be selected, but... 8 | void f(int i); // ... this version using the type int directly is even more close! 9 | 10 | 11 | 12 | int main() { 13 | f(1); // Call f(int i); 14 | } 15 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/overload2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | #include 5 | 6 | std::string f(...) // Variadic functions are so "untyped" that... 7 | { 8 | return "..."; 9 | } 10 | 11 | template 12 | std::string f(const T &t)// ...this templated function got the precedence! 13 | { 14 | 15 | return "T"; 16 | } 17 | 18 | int main() { 19 | std::cout << f(1) << std::endl; 20 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/p1SFINAE.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | 5 | /* 6 | The compiler will try this overload since it's less generic than the variadic. 7 | T will be replace by int which gives us void f(const int& t, int::iterator* b = nullptr); 8 | int doesn't have an iterator sub-type, but the compiler doesn't throw a bunch of errors. 9 | It simply tries the next overload. 10 | 11 | 编译器尝试此重载,因为模板化函数比可变参数函数更精确(通用)。T将被int取代,这将使我们得到 12 | void f(const int& t, int::iterator* b = nullptr); int 没有迭代器子类型,但是编译器不会抛出一堆错误。 13 | 它只是尝试下一个重载。 14 | */ 15 | template 16 | void f(const T &t, typename T::iterator *it = nullptr) {} 17 | 18 | // The sink-hole. 19 | void f(...) {} 20 | 21 | int main() { 22 | f(1); // Calls void f(...) { } 23 | } 24 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/p2SFINAE.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | 5 | 6 | // The compiler will be really unhappy when it will later discover the call to hahahaICrash. 7 | // 当以后发现对hahahaICrash的调用时,编译器将非常不满意。 8 | template void f(T t) { t.hahahaICrash(); } 9 | void f(...) { } // The sink-hole wasn't even considered. 10 | 11 | int main() { 12 | f(1); 13 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/serialize.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include "structData.h" 9 | using namespace std; 10 | 11 | namespace hana = boost::hana; 12 | // 检查类型是否有一个serialize方法 13 | auto hasSerialize = hana::is_valid([](auto &&x) -> decltype(x.serialize()) {}); 14 | 15 | // 序列化任意对象 16 | template 17 | std::string serialize(T const &obj) { 18 | return hana::if_(hasSerialize(obj), 19 | [](auto &x) { return x.serialize(); }, 20 | [](auto &x) { return to_string(x); } 21 | )(obj); 22 | } 23 | 24 | 25 | 26 | int main() { 27 | A a; 28 | B b; 29 | C c; 30 | std::cout << serialize(a) << std::endl; 31 | std::cout << serialize(b) << std::endl; 32 | std::cout << serialize(c) << std::endl; 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/sizeof1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | 5 | #include 6 | 7 | typedef char type_test[42]; 8 | 9 | type_test &f() {} 10 | 11 | int main() { 12 | 13 | // In the following lines f won't even be truly called but we can still access to the size of its return type. 14 | // Thanks to the "fake evaluation" of the sizeof operator. 15 | char arrayTest[sizeof(f())]; 16 | std::cout << sizeof(f()) << std::endl; // Output 42. 17 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/sizeof2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 4 | // Created by light on 20-1-6. 5 | // 6 | 7 | typedef char yes; // Size: 1 byte. 8 | typedef yes no[2]; // Size: 2 bytes. 9 | 10 | // Two functions using our type with different size. 11 | yes &f1() {} 12 | no &f2() {} 13 | 14 | int main() { 15 | std::cout << sizeof(f1()) << std::endl; 16 | std::cout << sizeof(f2()) << std::endl; 17 | std::cout << (sizeof(f1()) == sizeof(f2())) << std::endl; // Output 0. 18 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/SFINAE/sfinae paper/structData.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-6. 3 | // 4 | 5 | #ifndef MORDEN_C_STRUCTDATA_H 6 | #define MORDEN_C_STRUCTDATA_H 7 | // 类型A只有to_string 方法 8 | struct A { 9 | }; 10 | 11 | std::string to_string(const A &) { 12 | return "I am A"; 13 | } 14 | 15 | // 类型B有serialize方法 16 | struct B { 17 | std::string serialize() const { 18 | return "I am B"; 19 | } 20 | }; 21 | 22 | // 类型C有个serialize数据成员与to_string方法 23 | struct C { 24 | std::string serialize; 25 | }; 26 | 27 | std::string to_string(const C &) { 28 | return "I am C"; 29 | } 30 | #endif //MORDEN_C_STRUCTDATA_H 31 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/compilercompute/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/learn_class/modern_C++_30/compilercompute/a.out -------------------------------------------------------------------------------- /learn_class/modern_C++_30/compilercompute/factorial.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-28. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | template 10 | struct factorial { 11 | static_assert(n >= 0, "Arg must be non-negative"); 12 | static const int value = n * factorial::value; 13 | }; 14 | 15 | template<> 16 | struct factorial<0> { 17 | static const int value = 1; 18 | }; 19 | 20 | int main() { 21 | 22 | printf("%d\n", factorial<-1>::value); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/compilercompute/fmap.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-5. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | 11 | template< 12 | template 13 | class OutContainer = vector, 14 | typename F, class R> 15 | auto fmap(F &&f, R &&inputs) { 16 | typedef decay_t result_type; 17 | 18 | OutContainer> result; 19 | 20 | for (auto &&item:inputs) { 21 | result.push_back(f(item)); 22 | } 23 | return result; 24 | } 25 | 26 | // 对每一个数进行加1操作 27 | int add_1(int x) { 28 | return x + 1; 29 | } 30 | 31 | int main() { 32 | vector v{1, 2, 3, 4, 5}; 33 | auto result = fmap(add_1, v); 34 | 35 | for (auto item:result) 36 | cout << item << " "; 37 | cout<如果一只鸟走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,那么这只鸟就可以被当作鸭子。 6 | 7 | 鸭子类型使得开发者可以不使用继承体系来灵活地实现一些“约定”,尤其是使得混合不同来源、使用不同对象继承体系的代码成为可能。唯一的要求只是,这些不同的对象有“共通”的成员函数。这些成员函数应当有相同的名字和相同结构的参数(并不要求参数类型相同)。 8 | 9 | 在C++中实现鸭子类型可以通过模板或者说泛型编程。不管是类模板还是函数模板,编译器在看到其定义时只能做最基本的语法检查,真正的类型检查要在实例化(instantiation)的时候才能做。一般而言,这也是编译器会报错的时候。 10 | 11 | > “动态”多态和“静态”多态的对比 12 | 13 | “动态”多态解决的是运行时的行为变化—这个是无法在编译时确定的。“静态”多态或者“泛型”—解决的是很不同的问题,让适用于不同类型的“同构”算法可以用同一套代码来实现,实际上强调的是对代码的复用。 -------------------------------------------------------------------------------- /learn_class/modern_C++_30/constexpr/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/learn_class/modern_C++_30/constexpr/a.out -------------------------------------------------------------------------------- /learn_class/modern_C++_30/constexpr/container.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-16. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "output_container.h" 10 | 11 | 12 | using namespace std; 13 | 14 | int main() { 15 | map mp{ 16 | {1, 1}, 17 | {2, 4}, 18 | {3, 9}}; 19 | cout << mp << endl; 20 | vector> vv{ 21 | {1, 1}, 22 | {2, 4}, 23 | {3, 9}}; 24 | cout << vv << endl; 25 | 26 | pair p{1, 2}; 27 | cout << p << endl; 28 | 29 | set s{1, 2, 3}; 30 | cout << s << endl; 31 | 32 | vector v{'a', 'b'}; 33 | cout << v << endl; 34 | set vs{"a", "b"}; 35 | cout << vs << endl; 36 | 37 | map mm{ 38 | {1, "23"}, 39 | {2, "234hi"} 40 | }; 41 | cout << mm << endl; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/constexpr/sqrt.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-7. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | int sqr(int n) { 9 | return n * n; 10 | } 11 | 12 | int rand() { 13 | return std::rand(); 14 | } 15 | 16 | // constant expression 17 | constexpr int sqr1(int n) { 18 | return n * n; 19 | } 20 | 21 | constexpr int factorial(int n) { 22 | // n是普通的int 不能使用static_assert 23 | // static_assert(n>=0); //error 24 | // 正确方式 25 | if (n < 0) { 26 | throw std::invalid_argument( 27 | "Arg must be non-negative"); 28 | } 29 | 30 | if (n == 0) { 31 | return 1; 32 | } else { 33 | return n * factorial(n - 1); 34 | } 35 | } 36 | 37 | int main() { 38 | int a[sqr(3)]; // ok 39 | const int n1 = sqr(3); // ok 40 | 41 | constexpr int n = sqr1(3); // constexpr=constant expression 常量表达式 42 | std::array aa; // ok 43 | 44 | std::array b; // ok 45 | int cc[rand()]; 46 | return 0; 47 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/constexpr/test3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-10. 3 | // 4 | 5 | #include 6 | 7 | class test3 { 8 | public: 9 | 10 | int value; 11 | 12 | // constexpr const method - can't chanage the values of object fields and can be evaluated at compile time. 13 | constexpr int getvalue() const { 14 | return (value); 15 | } 16 | 17 | constexpr test3(int Value) 18 | : value(Value) { 19 | } 20 | }; 21 | 22 | 23 | int main() { 24 | 25 | // 加不加都行 26 | constexpr test3 x(100); // OK. Constructor is constexpr. 27 | 28 | int array[x.getvalue()]; // OK. x.getvalue() is constexpr and can be evaluated at compile time. 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/container1/container.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-16. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include "output_container.h" 9 | 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | map mp{ 15 | {1, 1}, {2, 4}, {3, 9}}; 16 | cout << mp << endl; 17 | vector> vv{ 18 | {1, 1}, {2, 4}, {3, 9}}; 19 | cout << vv << endl; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/container2/array.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-16. 3 | // 4 | 5 | #include 6 | #include // std::map 7 | #include "../container1/output_container.h" 8 | 9 | using namespace std; 10 | #define ARRAY_LEN(a) \ 11 | (sizeof(a) / sizeof((a)[0])) 12 | 13 | 14 | void test(int a[8]) { 15 | cout << ARRAY_LEN(a) << endl; 16 | } 17 | 18 | 19 | void test1(int arr[]) { 20 | // 不能编译 21 | // std::cout << std::size(arr) 22 | // << std::endl; 23 | } 24 | 25 | 26 | typedef char mykey_t[8]; 27 | typedef std::array mykey_t1; 28 | 29 | int main() { 30 | int a[8]; 31 | test(a); 32 | 33 | 34 | // C++17 直接提供了一个 size 方法,可以用于提供数组长度, 35 | int arr[] = {1, 2, 3, 4, 5}; 36 | std::cout << "The array length is " 37 | << std::size(arr) 38 | << std::endl; 39 | // 并且在数组退化成指针的情况下会直接失败 40 | test1(arr); 41 | 42 | 43 | std::map mp; 44 | mykey_t mykey{"hello"}; 45 | // mp[mykey] = 5; 46 | // 轰,大段的编译错误 47 | 48 | 49 | std::map mp1; 50 | mykey_t1 mykey1{"hello"}; 51 | mp1[mykey1] = 5; // ok 52 | cout << mp1 << endl; 53 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/container2/hash.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-16. 3 | // 4 | 5 | 6 | #include // std::sort 7 | #include // std::less/greater/hash 8 | #include // std::cout/endl 9 | #include // std::string 10 | #include // std::vector 11 | #include "../container1/output_container.h" 12 | 13 | using namespace std; 14 | 15 | int main() 16 | { 17 | // 初始数组 18 | vector v{13, 6, 4, 11, 29}; 19 | cout << v << endl; 20 | 21 | // 从小到大排序 22 | sort(v.begin(), v.end()); 23 | cout << v << endl; 24 | 25 | // 从大到小排序 26 | sort(v.begin(), v.end(), 27 | greater()); 28 | cout << v << endl; 29 | 30 | cout << hex; 31 | 32 | auto hp = hash(); 33 | cout << "hash(nullptr) = " 34 | << hp(nullptr) << endl; 35 | cout << "hash(v.data()) = " 36 | << hp(v.data()) << endl; 37 | cout << "v.data() = " 38 | << static_cast(v.data()) 39 | << endl; 40 | 41 | auto hs = hash(); 42 | cout << "hash(\"hello\") = " 43 | << hs(string("hello")) << endl; 44 | cout << "hash(\"hellp\") = " 45 | << hs(string("hellp")) << endl; 46 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/container2/priority_queue.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-16. 3 | // 4 | 5 | 6 | #include // std::greater 7 | #include // std::cout/endl 8 | #include // std::pair 9 | #include // std::priority_queue 10 | #include // std::vector 11 | #include "../container1/output_container.h" 12 | 13 | using namespace std; 14 | 15 | int main() 16 | { 17 | priority_queue< 18 | pair, 19 | vector>, 20 | greater>> 21 | q; 22 | q.push({1, 1}); 23 | q.push({2, 2}); 24 | q.push({0, 3}); 25 | q.push({9, 4}); 26 | while (!q.empty()) { 27 | cout << q.top() << endl; 28 | q.pop(); 29 | } 30 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/container2/unorder.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-16. 3 | // 4 | 5 | 6 | #include // std::complex 7 | #include // std::cout/endl 8 | #include // std::unordered_map 9 | #include // std::unordered_set 10 | #include "../container1/output_container.h" 11 | 12 | using namespace std; 13 | 14 | namespace std { 15 | 16 | template 17 | struct hash> { 18 | size_t 19 | operator()(const complex& v) const 20 | noexcept 21 | { 22 | hash h; 23 | return h(v.real()) + h(v.imag()); 24 | } 25 | }; 26 | 27 | } // namespace std 28 | 29 | int main() 30 | { 31 | unordered_set s{ 32 | 1, 1, 2, 3, 5, 8, 13, 21 33 | }; 34 | cout << s << endl; 35 | 36 | unordered_map, 37 | double> 38 | umc{{{1.0, 1.0}, 1.4142}, 39 | {{3.0, 4.0}, 5.0}}; 40 | cout << umc << endl; 41 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/exception/exception.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-17. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | // “首先是内存分配。如果 new 出错,按照 C++ 的规则,一般会得到异常 bad_alloc,对象的构造也就失败了。 9 | // 这种情况下,在 catch 捕捉到这个异常之前,所有的栈上对象会全部被析构,资源全部被自动清理。” 10 | // 之所以是栈上对象会全被被析构原因是堆上的东西都是由栈上的变量所引用的,栈上对象析构的过程, 11 | // 堆上相应的资源自然就被释放了。而且被释放的对象的范围还被栈帧限定了。 12 | 13 | 14 | // -fexceptions(缺省开启) 15 | // g++ test.cpp -std=c++17 -fno-exceptions 16 | // 关闭异常,可看到可执行文件的大小的变化。 17 | int main() 18 | { 19 | std::vector v{1, 2, 3, 4, 5}; 20 | v.push_back(20); 21 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/functionLambda/adder.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-11. 3 | // 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct adder { 9 | adder(int n) : n_(n) {} 10 | 11 | int operator()(int x) const { 12 | return x + n_; 13 | } 14 | 15 | private: 16 | int n_; 17 | }; 18 | 19 | int main() { 20 | auto add_2 = adder(2); 21 | 22 | // x+2 23 | cout << add_2(3) << endl; 24 | 25 | auto t = bind1st(plus(), 2); 26 | cout << t(1) << endl; 27 | // 上述的C++98 28 | binder2nd > a2(plus(), 2); 29 | cout << a2(3) << endl; 30 | 31 | cout << [](int x) { return x * x; }(3) << endl; 32 | return 0; 33 | // lambda表达式默认就是constexpr函数 34 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/functionLambda/function.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-1-11. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | 13 | map> 14 | op_dict{ 15 | {"+", 16 | [](int x, int y) { 17 | return x + y; 18 | }}, 19 | {"-", 20 | [](int x, int y) { 21 | return x - y; 22 | }}, 23 | {"*", 24 | [](int x, int y) { 25 | return x * y; 26 | }}, 27 | {"/", 28 | [](int x, int y) { 29 | return x / y; 30 | }}, 31 | }; 32 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/literalAssert/assert.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-25. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | int main() { 9 | const int alignment=5; 10 | assert((alignment & (alignment - 1)) == 0); 11 | static_assert((alignment & (alignment - 1)) == 0, "Alignment must be power of two"); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/literalAssert/default_delete.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-25. 3 | // 4 | 5 | class myFun { 6 | public: 7 | myFun() = default; 8 | 9 | myFun(const myFun &) = default; 10 | 11 | myFun &operator=(const myFun &) = default; 12 | 13 | myFun(myFun &&) = delete; 14 | 15 | myFun &operator=(myFun &&) = delete; 16 | 17 | ~myFun() = default; 18 | }; -------------------------------------------------------------------------------- /learn_class/modern_C++_30/literalAssert/overridefinal.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-25. 3 | // 4 | 5 | 6 | class A { 7 | public: 8 | virtual void foo(); 9 | virtual void bar(); 10 | void foobar(); 11 | }; 12 | 13 | class B : public A { 14 | public: 15 | void foo() override; // OK 16 | void bar() override final; // OK 17 | //void foobar() override; 18 | // 非虚函数不能 override 19 | }; 20 | 21 | class C final : public B { 22 | public: 23 | void foo() override; // OK 24 | //void bar() override; 25 | // final 函数不可 override 26 | }; 27 | 28 | class D : public C { 29 | // 错误:final 类不可派生 30 | }; -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/barrier_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | #include 5 | 6 | using namespace std; 7 | 8 | #include 9 | 10 | #define barrier() __asm__ volatile ("lwsync") 11 | 12 | // method 1 operator new + placement new 13 | //singleton *instance() { 14 | // if (p == nullptr) { 15 | // lock_guard guard(lock_); 16 | // if (p == nullptr) { 17 | // singleton *tmp = static_cast(operator new(sizeof(singleton))); 18 | // new(p)singleton(); 19 | // p = tmp; 20 | // } 21 | // } 22 | // return p; 23 | //} 24 | class singleton { 25 | private: 26 | singleton() {} 27 | 28 | static singleton *p; 29 | static mutex lock_; 30 | public: 31 | static singleton *instance(); 32 | }; 33 | 34 | singleton *singleton::p = nullptr; 35 | 36 | singleton *singleton::instance() { 37 | if (p == nullptr) { 38 | lock_guard guard(lock_); 39 | barrier(); 40 | if (p == nullptr) { 41 | p = new singleton(); 42 | } 43 | } 44 | return p; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/cpulpuls11_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | #include 10 | #include 11 | 12 | //C++ 11版本之后的跨平台实现 13 | class singleton { 14 | private: 15 | singleton() {} 16 | 17 | static mutex lock_; 18 | static atomic p; 19 | public: 20 | singleton *instance(); 21 | }; 22 | 23 | mutex singleton::lock_; 24 | atomic singleton::p; 25 | 26 | /* 27 | * std::atomic_thread_fence(std::memory_order_acquire); 28 | * std::atomic_thread_fence(std::memory_order_release); 29 | * 这两句话可以保证他们之间的语句不会发生乱序执行。 30 | */ 31 | singleton *singleton::instance() { 32 | singleton *tmp = p.load(memory_order_relaxed); 33 | atomic_thread_fence(memory_order_acquire); 34 | if (tmp == nullptr) { 35 | lock_guard guard(lock_); 36 | tmp = p.load(memory_order_relaxed); 37 | if (tmp == nullptr) { 38 | tmp = new singleton(); 39 | atomic_thread_fence(memory_order_release); 40 | p.store(tmp, memory_order_relaxed); 41 | } 42 | } 43 | return p; 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/dcl_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | #include 5 | 6 | using namespace std; 7 | 8 | #include 9 | 10 | class singleton { 11 | private: 12 | singleton() {} 13 | 14 | static singleton *p; 15 | static mutex lock_; 16 | public: 17 | singleton *instance(); 18 | 19 | // 实现一个内嵌垃圾回收类 20 | class CGarbo 21 | { 22 | public: 23 | ~CGarbo() 24 | { 25 | if(singleton::p) 26 | delete singleton::p; 27 | } 28 | }; 29 | static CGarbo Garbo; // 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象 30 | }; 31 | 32 | singleton *singleton::p = nullptr; 33 | singleton::CGarbo Garbo; 34 | 35 | singleton* singleton::instance() { 36 | if (p == nullptr) { 37 | lock_guard guard(lock_); 38 | if (p == nullptr) 39 | p = new singleton(); 40 | } 41 | return p; 42 | } 43 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/hungrysingleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-6. 3 | // 4 | 5 | class singleton { 6 | private: 7 | singleton() {} 8 | static singleton *p; 9 | public: 10 | static singleton *instance(); 11 | }; 12 | 13 | singleton *singleton::p = new singleton(); 14 | singleton* singleton::instance() { 15 | return p; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/iazysingleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-6. 3 | // 4 | 5 | class singleton { 6 | private: 7 | singleton() {} 8 | static singleton *p; 9 | public: 10 | static singleton *instance(); 11 | }; 12 | 13 | singleton *singleton::p = nullptr; 14 | 15 | singleton* singleton::instance() { 16 | if (p == nullptr) 17 | p = new singleton(); 18 | return p; 19 | } 20 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/lock_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | 9 | class singleton { 10 | private: 11 | singleton() {} 12 | static singleton *p; 13 | static mutex lock_; 14 | public: 15 | static singleton *instance(); 16 | }; 17 | 18 | singleton *singleton::p = nullptr; 19 | 20 | singleton* singleton::instance() { 21 | lock_guard guard(lock_); 22 | if (p == nullptr) 23 | p = new singleton(); 24 | return p; 25 | } 26 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/pthreadoncesingleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-6. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | class singleton { 9 | private: 10 | singleton(); //私有构造函数,不允许使用者自己生成对象 11 | singleton(const singleton &other); 12 | 13 | //要写成静态方法的原因:类成员函数隐含传递this指针(第一个参数) 14 | static void init() { 15 | p = new singleton(); 16 | } 17 | 18 | static pthread_once_t ponce_; 19 | static singleton *p; //静态成员变量 20 | public: 21 | singleton *instance() { 22 | // init函数只会执行一次 23 | pthread_once(&ponce_, &singleton::init); 24 | return p; 25 | } 26 | }; 27 | 28 | 29 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/memorymodel_atomic/static_local_singleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 20-2-7. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | class singleton { 10 | private: 11 | static singleton *p; 12 | singleton() {} 13 | public: 14 | singleton *instance(); 15 | }; 16 | 17 | singleton *singleton::instance() { 18 | static singleton p; 19 | return &p; 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /learn_class/modern_C++_30/reference/don'treturnReference.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-15. 3 | // 4 | 5 | #include // std::cout/endl 6 | #include // std::move 7 | using namespace std; 8 | class Obj { 9 | public: 10 | Obj() 11 | { 12 | cout << "Obj()" << endl; 13 | } 14 | Obj(const Obj&) 15 | { 16 | cout << "Obj(const Obj&)" 17 | << endl; 18 | } 19 | Obj(Obj&&) 20 | { 21 | cout << "Obj(Obj&&)" << endl; 22 | } 23 | }; 24 | Obj simple() 25 | { 26 | Obj obj; 27 | // 简单返回对象;一般有 NRVO 28 | return obj; 29 | } 30 | Obj simple_with_move() 31 | { 32 | Obj obj; 33 | // move 会禁止 NRVO 34 | return std::move(obj); 35 | } 36 | Obj complicated(int n) 37 | { 38 | Obj obj1; 39 | Obj obj2; 40 | // 有分支,一般无 NRVO 41 | if (n % 2 == 0) { 42 | return obj1; 43 | } else { 44 | return obj2; 45 | } 46 | } 47 | int main() 48 | { 49 | cout << "*** 1 ***" << endl; 50 | auto obj1 = simple(); 51 | cout << "*** 2 ***" << endl; 52 | auto obj2 = simple_with_move(); 53 | cout << "*** 3 ***" << endl; 54 | auto obj3 = complicated(42); 55 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/returnObj/returnObj1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-22. 3 | // 4 | 5 | 6 | // rvo example 7 | 8 | #include 9 | 10 | using namespace std; 11 | 12 | // Can copy and move 13 | class A { 14 | public: 15 | A() { cout << "Create A\n"; } 16 | 17 | ~A() { cout << "Destroy A\n"; } 18 | 19 | A(const A &) { cout << "Copy A\n"; } 20 | 21 | A(A &&) { cout << "Move A\n"; } 22 | 23 | 24 | A& operator=(const A&a) 25 | { 26 | std::cout << "copy assignment" << std::endl; 27 | return *this; 28 | } 29 | 30 | A& operator=(A &&a) { 31 | cout << "move assignment\n"; 32 | return *this; 33 | } 34 | 35 | }; 36 | 37 | // 编译器可以优化 返回值移动出去 38 | A getA_unnamed() { 39 | return A(); 40 | } 41 | 42 | int main() { 43 | // cout<<"构造"< 8 | 9 | using namespace std; 10 | 11 | // Can copy and move 12 | class A { 13 | public: 14 | A() { cout << "Create A\n"; } 15 | 16 | ~A() { cout << "Destroy A\n"; } 17 | 18 | A(const A &) { cout << "Copy A\n"; } 19 | 20 | A(A &&) { cout << "Move A\n"; } 21 | 22 | 23 | A& operator=(const A&a) 24 | { 25 | std::cout << "copy assignment" << std::endl; 26 | return *this; 27 | } 28 | 29 | A& operator=(A &&a) { 30 | cout << "move assignment\n"; 31 | return *this; 32 | } 33 | }; 34 | 35 | // 编译器可以优化 返回值移动出去 36 | A getA_named() { 37 | A a; 38 | return a; 39 | } 40 | 41 | int main() { 42 | // cout<<"拷贝"< 7 | 8 | using namespace std; 9 | 10 | // Can copy and move 11 | class A { 12 | public: 13 | A() { cout << "Create A\n"; } 14 | 15 | ~A() { cout << "Destroy A\n"; } 16 | 17 | A(const A &) { cout << "Copy A\n"; } 18 | 19 | A(A &&) { cout << "Move A\n"; } 20 | 21 | A& operator=(const A&a) 22 | { 23 | std::cout << "copy assignment" << std::endl; 24 | return *this; 25 | } 26 | 27 | A& operator=(A &&a) { 28 | cout << "move assignment\n"; 29 | return *this; 30 | } 31 | }; 32 | // 编译器无法优化 33 | A getA_duang() { 34 | A a1; 35 | A a2; 36 | if (rand() > 42) { 37 | return a1; 38 | } 39 | else { 40 | return a2; 41 | } 42 | } 43 | 44 | int main() { 45 | // cout<<"拷贝"< 7 | 8 | using namespace std; 9 | 10 | // Can copy and move 11 | class A { 12 | public: 13 | A() { cout << "Create A\n"; } 14 | 15 | ~A() { cout << "Destroy A\n"; } 16 | 17 | A(const A &) { cout << "Copy A\n"; } 18 | 19 | A(A&&)= delete; 20 | }; 21 | 22 | A getA_duang() { 23 | A a1; 24 | A a2; 25 | if (rand() > 42) { 26 | return a1; 27 | } 28 | else { 29 | return a2; 30 | } 31 | } 32 | 33 | int main() { 34 | auto a = getA_duang(); 35 | } -------------------------------------------------------------------------------- /learn_class/modern_C++_30/returnObj/returnObj5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by light on 19-12-22. 3 | // 4 | 5 | 6 | #include 7 | 8 | using namespace std; 9 | 10 | // Can copy and move 11 | class A { 12 | public: 13 | A() { cout << "Create A\n"; } 14 | 15 | ~A() { cout << "Destroy A\n"; } 16 | 17 | // A(const A &) { cout << "Copy A\n"; } 18 | // 19 | // A(A &&) { cout << "Move A\n"; } 20 | 21 | A(const A&&)= delete; 22 | A(A&&)= delete; 23 | }; 24 | 25 | A getA_unnamed() { 26 | return A(); 27 | } 28 | 29 | int main() { 30 | auto a = getA_unnamed(); 31 | } -------------------------------------------------------------------------------- /practical_exercises/.README.md.un~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/.README.md.un~ -------------------------------------------------------------------------------- /practical_exercises/10_day_practice/day1/打印练习.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int main(int argc, char const *argv[]) 4 | { 5 | int i,j,k,f; 6 | for (i=1;i<=4;i++){ 7 | for (j=1;j<=30;j++) 8 | cout<<" "; 9 | for (k=1;k<=8-2*i;k++) 10 | cout<<" "; 11 | for (f=1;f<=2*i;f++) 12 | cout<<'*'; 13 | cout< 2 | using namespace std; 3 | int main(int argc, char const *argv[]) 4 | { 5 | int year; 6 | bool isLeapYear; 7 | cout<<"Enter the year: "; 8 | cin>>year; 9 | isLeapYear = (((year%4==0)&&(year%100!=0))||(year%400==0)); 10 | if(isLeapYear) 11 | { 12 | cout< 2 | using namespace std; 3 | int main(int argc, char const *argv[]) 4 | { 5 | char stu[5][10]; 6 | int i; 7 | for(i=0;i<5;i++) 8 | cin.getline(stu[i],10,','); 9 | for(i=0;i<5;i++) 10 | cout< 3 | #include 4 | using namespace std; 5 | int main(){ 6 | char ch; 7 | ofstream out("/test.dat",ios::out|ios::binary); //L1 8 | for(int i=0;i<90;i++){ 9 | if(i>0 && (i % 30)==0) 10 | out.put('\n'); 11 | out.put(i); 12 | out.put(' '); 13 | 14 | } 15 | out.close(); 16 | ifstream in("/test.dat",ios::in|ios::binary); 17 | while(in.get(ch)) 18 | cout< 2 | using namespace std; 3 | 4 | int main(int argc, char const *argv[]) 5 | { 6 | char c[30]="this is string"; 7 | double d = -1231.232; 8 | cout.width(30); 9 | cout.fill('*'); 10 | cout.setf(ios::left); 11 | cout< 2 | using namespace std; 3 | double power(double x, int n); 4 | 5 | int main(int argc, char const *argv[]) 6 | { 7 | int x; 8 | cin>>x; 9 | int wei=0; 10 | int sum=0; 11 | int each,chu; 12 | for(int i=0;i<8;i++) 13 | { 14 | each=x%10; 15 | chu=x/10; 16 | sum+=each*power(2,wei); 17 | x=chu; 18 | wei++; 19 | } 20 | cout< 2 | using namespace std; 3 | double arctan(double x); 4 | int main(int argc, char const *argv[]) 5 | { 6 | double a = 16.0*arctan(1.0/5.0); 7 | double b = 4.0*arctan(1.0/239.0); 8 | double pi = a-b; 9 | cout<1e-15) 19 | { 20 | art=(tail%4==1)? art+head/tail: art-head/tail; 21 | head*=x*x; 22 | tail+=2; 23 | cout<<"---------------"< 2 | using namespace std; 3 | struct student 4 | { 5 | int num; 6 | char name[20]; 7 | char gender; 8 | }; 9 | 10 | int main(int argc, char const *argv[]) 11 | { 12 | student s={10,"asd",'M'}; 13 | cout< 2 | using namespace std; 3 | 4 | int f(int n); 5 | int main(int argc, char const *argv[]) 6 | { 7 | cout<<"input x:"; 8 | int x; 9 | cin>>x; 10 | cout< 2 | using namespace std; 3 | void swap(int & a, int & b); 4 | int main(int argc, char const *argv[]) 5 | { 6 | int x1(5); 7 | int x2(7); 8 | swap(x1,x2); 9 | cout< 2 | using namespace std; 3 | class Time{ 4 | private: 5 | int hh,mm,ss; 6 | public: 7 | Time(int h=0,int m=0,int s=0):hh(h),mm(m),ss(s){} 8 | void operator()(int h,int m,int s) { 9 | hh=h; 10 | mm=m; 11 | ss=s; 12 | } 13 | void ShowTime(){ 14 | cout< 3 | using namespace std; 4 | class A { 5 | int x; 6 | public: 7 | A(int i=0) { 8 | x=i; 9 | cout << "A-----"< 2 | using namespace std; 3 | class A { 4 | public: 5 | A(){ cout<<"Constructing A"< 2 | using namespace std; 3 | class A { 4 | public: 5 | void vf() { 6 | cout<<"I come from class A"< 2 | using namespace std; 3 | class A { 4 | public: 5 | void vf() { 6 | cout<<"I come from class A"< 2 | using namespace std; 3 | class B{ 4 | public: 5 | void f(){ g(); } 6 | virtual void g(){ cout << "B::g"; } 7 | }; 8 | class D : public B{ 9 | public: 10 | void g(){ cout << "D::g\n"; } 11 | }; 12 | int main(){ 13 | D d; 14 | d.f(); 15 | system("pause"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /practical_exercises/10_day_practice/day6/虚函数/编程实例.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/10_day_practice/day6/虚函数/编程实例.cpp -------------------------------------------------------------------------------- /practical_exercises/10_day_practice/day6/虚函数/虚函数例子.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/10_day_practice/day6/虚函数/虚函数例子.cpp -------------------------------------------------------------------------------- /practical_exercises/10_day_practice/day6/虚函数/虚函数特性.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/10_day_practice/day6/虚函数/虚函数特性.cpp -------------------------------------------------------------------------------- /practical_exercises/10_day_practice/day6/虚函数/虚析构函数.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | class A{ 5 | public: 6 | virtual ~A(){ cout<<"call A::~A()"< 2 | using namespace std; 3 | class Time{ 4 | private: 5 | int hh,mm,ss; 6 | public: 7 | Time(int h=0,int m=0,int s=0):hh(h),mm(m),ss(s){} 8 | void operator()(int h,int m,int s) { 9 | hh=h; 10 | mm=m; 11 | ss=s; 12 | } 13 | void ShowTime(){ 14 | cout< 2 | using namespace std; 3 | class X 4 | {public: 5 | int operator() (int i=0) 6 | { cout << "X::operator(" << i << ")" << endl; return i; }; 7 | int operator() (int i, int j) 8 | { cout << "X::operator(" << i << "," << j << ")" << endl; 9 | return i; }; 10 | int operator[] (int i) 11 | { cout << "X::operator[" << i << "]" << endl; return i; }; 12 | int operator[] (char * cp) 13 | { cout << "X::operator[" << cp << "]" << endl; return 0; }; 14 | }; 15 | int main (void) 16 | { X obj; int i = obj (obj (1), 2); 17 | int a = obj[i]; int b = obj["abcd"]; 18 | cout<<"a="< 3 | using namespace std; 4 | int main(){ 5 | cout<<"1--befroe try block..."< 3 | using namespace std; 4 | const int MAX=3; 5 | class Full{ 6 | int a; 7 | public: 8 | Full(int i):a(i){} 9 | int getValue(){return a;} 10 | }; 11 | class Empty{}; 12 | class Stack{ 13 | private: 14 | int s[MAX]; 15 | int top; 16 | public: 17 | Stack(){top=-1;} 18 | void push(int a){ 19 | if(top>=MAX-1) 20 | throw Full(a); 21 | s[++top]=a; 22 | } 23 | int pop(){ 24 | if(top<0) 25 | throw Empty(); 26 | return s[top--]; 27 | } 28 | }; 29 | int main(){ 30 | Stack s; 31 | try{ 32 | s.push(10); 33 | s.push(20); 34 | s.push(30); 35 | s.push(40); 36 | } 37 | catch(Full e){ 38 | cout<<"Exception: Stack Full..."< 2 | using namespace std; 3 | void temperature(int t) 4 | { 5 | try{ 6 | if(t==100) throw "It's at the boiling point."; 7 | else if(t==0) throw "It reached the freezing point"; 8 | else cout<<"the temperature is OK..."< 3 | using namespace std; 4 | 5 | void handler(int n)throw(int,char,double){ 6 | if(n==1) throw n; 7 | if(n==2) throw 'x'; 8 | if(n==3) throw 1.1; 9 | } 10 | int main(){ 11 | cout<<"Before handler..."< 3 | using namespace std; 4 | void Errhandler(int n)throw(){ 5 | try{ 6 | if(n==1) throw n; 7 | if(n==2) throw "dx"; 8 | if(n==3) throw 1.1; 9 | } 10 | catch(...){cout<<"catch an exception..."< 3 | using namespace std; 4 | class A{ 5 | int a; 6 | public: 7 | A(int i=0):a(i){} 8 | ~A(){cout<<"in A destructor..."< 2 | #include 3 | using namespace std; 4 | 5 | 6 | template T compareMax(T t1,T t2){ 7 | return t1>t2?t1:t2; 8 | } 9 | 10 | template<> char* compareMax(char *s1,char *s2){ 11 | return strcmp(s1,s2)>=0?s1:s2; 12 | } 13 | int main(int argc, char const *argv[]) 14 | { 15 | cout< 2 | #include 3 | 4 | 5 | int main() { 6 | 7 | char *sPtr; 8 | const char* s="hello"; 9 | sPtr = new char[strlen(s)+1]; 10 | strncpy(sPtr,s,strlen(s)); 11 | std::cout << sPtr << std::endl; 12 | delete sPtr; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /practical_exercises/key_exercises/字典插入与查找.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/字典插入与查找.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/异常捕获.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/异常捕获.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/时钟++运算符重载.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/时钟++运算符重载.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/类模板之栈.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/类模板之栈.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/类模板特化之数组.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/类模板特化之数组.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/继承与封装.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/继承与封装.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/读写文件综合题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/读写文件综合题.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/输入输出运算符重载.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/输入输出运算符重载.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/输入输出重载.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/输入输出重载.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/输出格式.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/输出格式.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/运算符重载之强制转换.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggplanty/CPlusPlusThingsPlus/73f19b640fbee00fddb9bd84c6d75248aa48fa4a/practical_exercises/key_exercises/运算符重载之强制转换.cpp -------------------------------------------------------------------------------- /practical_exercises/key_exercises/重载圆括号的时钟.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class Time{ 4 | private: 5 | int hh,mm,ss; 6 | public: 7 | Time(int h=0,int m=0,int s=0):hh(h),mm(m),ss(s){} 8 | void operator()(int h,int m,int s) { 9 | hh=h; 10 | mm=m; 11 | ss=s; 12 | } 13 | void ShowTime(){ 14 | cout< 6 | #include 7 | #include 8 | #include 9 | #include "output_container.h" 10 | 11 | 12 | using namespace std; 13 | 14 | int main() { 15 | map mp{ 16 | {1, 1}, 17 | {2, 4}, 18 | {3, 9}}; 19 | cout << mp << endl; 20 | vector> vv{ 21 | {1, 1}, 22 | {2, 4}, 23 | {3, 9}}; 24 | cout << vv << endl; 25 | 26 | pair p{1, 2}; 27 | cout << p << endl; 28 | 29 | set s{1, 2, 3}; 30 | cout << s << endl; 31 | 32 | vector v{'a', 'b'}; 33 | cout << v << endl; 34 | set vs{"a", "b"}; 35 | cout << vs << endl; 36 | 37 | map mm{ 38 | {1, "23"}, 39 | {2, "234hi"} 40 | }; 41 | cout << mm << endl; 42 | 43 | } 44 | --------------------------------------------------------------------------------