文章目录

  • C++的编程思想和进阶编程
    • 软件设计模式
    • 泛型编程的思想
    • STL
      • 六大组件
        • 容器
        • 仿函数
        • 算法
        • 迭代器
        • 适配器
        • 空间配置器(allocator)
      • 总结
    • C++多线程

C++的编程思想和进阶编程

软件设计模式

  • 一个模式描述了一个不断发生的问题以及这个问题的解决方案;模式是前人的设计经验上总结出来的对于一些普遍存在的问题提供的通用的解决方案;比如单例模式、观察者模式等

  • 软件中有很多模式

    面向对象常见的23中设计模式;

    反模式;企业应用架构模式等

泛型编程的思想

  • 如果说面向对象是一种通过间接层来调用函数,以换取一种抽象,那么泛型编程则是更直接的抽象,它不会因为间接层而损失效率
  • 不同于面向对象的动态期多态(运行时多态),泛型编程是一种静态多态(编译时多态),通过编译器生成最直接的代码
  • 泛型编程可以将算法与特定类型、结构剥离,尽可能的复用代码

模板编程的难点很大程度上在于对编译器的理解,我们需要知道怎么帮助编译器提供需要生成代码的信息。

STL

  • STL算法是泛型,不与任何特定数据结构和对象绑定,不必在环境类型的情况下重写代码
  • STL算法可以量身定做,并且有很高的效率
  • STL可以进行扩充,你可以编写自己的组件并且能与STL标准的组件进行很好的配合

六大组件

容器、仿函数、算法、空间配置器、适配器、迭代器

容器

  • 容器用于存放数据;STL的容器分为两大类

    • 序列式容器

      其元素都是可排序的,STL提供了vector/list/deque等序列同期。而stack,queue,priority_queue则是容器适配器

    • 关联式容器

      每个数据元素都是由一个键(key)和值(value)组成,当元素被插入到容器时,按照其键以某种特定规则放入释放位置;常见的stl关联容器:set map

仿函数

  • 仿函数一般不会单独使用,主要是为了搭配STL算法使用
  • 函数指针不能满足STL对抽象性的要求,不能满足软件积木的要求,无法和STL其他组件搭配
  • 本质就是类重载了一个operator(),创建了一个行为类似于函数的对象
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <functional>
#include<algorithm>
#include <utility>
#include <iostream>
using namespace std;
struct Display
{void operator()(int i){cout << i << " ";}
};struct Display2
{void operator()(pair<string, double> info){cout << info.first << ":  " << info.second << "  ";}
};//struct cmpMap
//{//  bool operator()(pair<string, double> a, pair<string, double> b)
//  {//      return a.first.length() < b.first.length();
//  }
//};
int main()
{int iArr[] = { 1, 2,3,4,5 };vector<int> iVector(iArr, iArr + 4);list<int> iList(iArr, iArr + 4);deque<int> iDeque(iArr, iArr + 4);queue<int> iQueue(iDeque);     // 队列 先进先出stack<int> iStack(iDeque);         // 栈 先进后出priority_queue<int> iPQueue(iArr, iArr + 4);  // 优先队列,按优先权 for_each( iVector.begin(), iVector.end(), Display() );cout << endl;for_each(iList.begin(), iList.end(), Display());cout << endl;for_each(iDeque.begin(), iDeque.end(), Display());cout << endl;while ( !iQueue.empty() ){cout << iQueue.front() << " ";  // 1  2 3 4iQueue.pop();}cout << endl;while (!iStack.empty()){cout << iStack.top() << " ";    // 4 3  2  1iStack.pop();}cout << endl;while (!iPQueue.empty()){cout << iPQueue.top() << " "; // 4 3 2 1iPQueue.pop();}cout << endl;return 0;
}
#include <string>
#include<map>
#include <algorithm>
#include <iostream>
using namespace std;
struct Display
{void operator()(pair<string, double> info){cout << info.first << ": " << info.second << endl;}
};
int main()
{map<string, double> studentSocres;studentSocres["LiMing"] = 95.0;studentSocres["LiHong"] = 98.5;studentSocres.insert( pair<string, double>("zhangsan", 100.0) );studentSocres.insert(pair<string, double>("Lisi", 98.6));studentSocres.insert(pair<string, double>("wangwu", 94.5));studentSocres.insert(map<string, double>::value_type("zhaoliu", 95.5) );studentSocres["wangwu"] = 88.5;for_each(studentSocres.begin(), studentSocres.end(), Display());cout << endl;map<string, double>::iterator iter;iter = studentSocres.find("zhaoliu");if (iter != studentSocres.end()){cout << "Found the score is: " << iter->second << endl;}else{cout << "Didn't find the key." << endl;}// 使用迭代器完成遍历查找的过程iter = studentSocres.begin();while (iter != studentSocres.end()){if (iter->second < 98.0)  // 去除不是优秀的同学{studentSocres.erase(iter++);  // 注意:迭代器失效问题}else{iter++;}}for_each(studentSocres.begin(), studentSocres.end(), Display());cout << endl;for (iter = studentSocres.begin(); iter != studentSocres.end(); iter++){if (iter->second <= 98.5){iter = studentSocres.erase(iter);  // 注意:迭代器失效问题}}for_each(studentSocres.begin(), studentSocres.end(), Display());cout << endl;// find得到并删除元素//iter = studentSocres.find("LiHong");//studentSocres.erase(iter);//for_each(studentSocres.begin(), studentSocres.end(), Display());//int n = studentSocres.erase("LiHong1");//cout << n << endl;//for_each(studentSocres.begin(), studentSocres.end(), Display());studentSocres.erase(studentSocres.begin(), studentSocres.end());for_each(studentSocres.begin(), studentSocres.end(), Display());cout << endl;return 0;
}

算法

  • STL中算法大致分为4类:包含于<algorithm> <numeric> <functional>

    • 非可变排序算法:指的是不直接修改其操作的容器内容的算法
    • 可变排序算法:修改他们操作的容器内容的算法
    • 排序算法:包括堆序列进行排序和合并的算法,搜索算法以及有序序列上的集合操作
    • 数值算法:对容器内容进行数值计算
  • 最长见的算法包括:

    查找、排序和通用算法,排列组合算法,集合算法等

#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
#include<iostream>
using namespace std;
int main()
{   // transform和lambda表达式int ones[] = { 1, 2, 3, 4, 5 };int twos[] = { 10, 20, 30, 40, 50 };int results[5];transform(ones, ones + 5, twos, results, std::plus<int>()); // 数组元素依次相加并返回for_each(results, results + 5,[ ](int a)->void {cout << a << endl; } ); // lambda表达式(匿名函数)cout << endl;// findint arr[] = { 0, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8 };int len = sizeof(arr) / sizeof(arr[0]);vector<int> iA(arr + 2, arr + 6);   // {2,3,3,4}//vector<int> iA;//iA.push_back(1);//iA.push_back(9); // {1, 9}cout << count(arr, arr + len, 6) << endl; // 统计6的个数cout << count_if(arr, arr + len, bind2nd(less<int>(),  7) ) << endl; // 统计<7的个数cout << binary_search(arr, arr + len, 9) << endl;   // 9找不到cout << *search(arr, arr + len, iA.begin(), iA.end()) << endl; // 查找子序列cout << endl;return 0;
}
#include <algorithm>
#include <iostream>
using namespace std;
// 输入一个不存在重复字符的字符串,打印出字符串中字符的全排列。
//比如:
//输入: "123"   3*2*1 = 3!
//输出:  123
//          132
//          213
//          231
//          321
//          312
//f(123) = 1+f(23), f(23) = 2+f(3), f(3)  = 3  递归
void swap(char* a, char* b)
{char temp = *a;*a = *b;*b = temp;
}
void Permutation(char* pStr, char* pPostion)
{// 基准点if (*pPostion == '\0'){cout << pStr << endl;}else{for (char* pChar = pPostion; *pChar != '\0'; pChar++){// 依次和后面的字符交换swap(*pChar, *pPostion);Permutation(pStr, pPostion + 1);// 换回来swap(*pChar, *pPostion);}}
}
int main()
{char test[] = "132";Permutation(test, test);cout << endl;// 用STL输出全排列// 注意:必须要保证数组顺序,do{cout << test[0] << test[1] << test[2] << endl;} while (next_permutation(test, test + 3));cout << endl;char test2[] = "321";// 注意:必须要保证数组顺序,do{cout << test2[0] << test2[1] << test2[2] << endl;} while (prev_permutation(test2, test2 + 3));return 0;
}

迭代器

  • 是一种smart point,用于访问顺序容器和关联容器中的元素,相当于容器和操作容器的算法之间的中介

  • 迭代器按照定义方式分为四种:

    1. 正向迭代器:iterator
    2. 常量正向迭代器:const_iterator
    3. 反向迭代器:reverse_iterator
    4. 常量反向迭代器:const_reverse_iterator
#include <list>
#include <iostream>
using namespace std;int main()
{list<int> v;v.push_back(3);v.push_back(4);v.push_front(2);v.push_front(1);  // 1, 2, 3, 4list<int>::const_iterator it;for (it = v.begin(); it != v.end(); it++){//*it += 1;cout << *it << " ";}cout << endl;// 注意:迭代器不支持<//for (it = v.begin(); it < v.end(); it++)//{// cout << *it << " ";//}cout <<v.front() << endl;v.pop_front();  // 从顶部去除list<int>::reverse_iterator it2;for (it2 = v.rbegin(); it2 != v.rend(); it2++){*it2 += 1;cout << *it2 << " ";                          // 5 4 3}cout << endl;return 0;
}

适配器

  • stack 栈:一种先进后出的容器,底层为deque
  • queue 队列:一种先进先出的容器,底层为deque
  • priority_queue 优先队列:一种特殊的队列,他能够在队列中进行排序(堆排序),底层实现结构式vector或者deque
#include <functional>
#include <stack>
#include <queue>
#include <iostream>
using namespace std;
int main()
{//stack<int> s;//queue<int> q;priority_queue<int> pq;  // 默认是最大值优先priority_queue<int, vector<int>, less<int> > pq2; //   最大值优先priority_queue<int, vector<int>, greater<int> > pq3; // 最小值优先pq.push(2);pq.push(1);pq.push(3);pq.push(0);while (!pq.empty()){int top = pq.top();cout << " top is: " << top<< endl;pq.pop();}cout << endl;pq2.push(2);pq2.push(1);pq2.push(3);pq2.push(0);while (!pq2.empty()){int top = pq2.top();cout << " top is: " << top << endl;pq2.pop();}cout << endl;pq3.push(2);pq3.push(1);pq3.push(3);pq3.push(0);while (!pq3.empty()){int top = pq3.top();cout << " top is: " << top << endl;pq3.pop();}cout << endl;return 0;
}

空间配置器(allocator)

《STL源码分析》

  • 从使用角度看,allocator隐藏在其他组件中默默工作,不需要关心,但是从stl实现角度看,它是首先分析的组件
  • allocator的分析可以提现C++在性能和资源管理上优化思想

jjalloc.h

#pragma once
#ifndef _JJALLOC
#define _JJALLOC
#include<new> //for placement new
#include<cstddef> //for ptrdiff_t ,size_t
#include<cstdlib> //for exit()
#include<climits> //for UINX_MAX
#include<iostream> //for cerrnamespace  JJ
{template<class T>inline T* _allocate(ptrdiff_t size, T*){set_new_handler(0);T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));if (tmp == 0){cerr << "out of memory" << endl;exit(1);}return tmp;}template<class T>inline void _deallocate(T* buffer){::operator delete(buffer);}template<class T1, class T2>inline void _construct(T1* p, const T2& value){new(p) T1(value);//placement new,invoke constuctor of T1}template<class T>inline void _destroy(T* ptr){ptr->~T();}template<class T>class allocator {public:typedef T value_type;typedef T* pointer;typedef const T* const_pointer;typedef T& reference;typedef const T& const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;//rebind allocator of type Utemplate<class U>struct rebind {typedef allocator<U> other;};//需要加上以下2个函数,windows的编译器用到了allocator不同类型的拷贝, allocator(){return;}template <class U>allocator(const allocator<U>& c){}//hint user for locality,第2个参数是个提示,实现上可能会利用它来增进区域性(locality),或完全忽略之pointer allocate(size_type n, const void* hint = 0){return _allocate((difference_type)n, (pointer)0);}void deallocate(pointer p, size_type n){_deallocate(p);}void construct(pointer p, const T& value){_construct(p, value);}void destroy(pointer p){_destroy(p);}pointer address(reference x) { return (pointer)&x; }const_pointer const_address(const_reference x) { return (const_pointer)&x; }size_type max_size() const {return size_type(UINT_MAX / sizeof(T));}};
}//#end of namespace JJ
#endif
#include "jjalloc.h"
#include <vector>
using namespace std;int main()
{int ia[5] = { 0, 1, 2, 3, 4 };unsigned int i;vector<int, JJ::allocator<int> > iv(ia, ia + 5);for (i = 0; i < iv.size(); i++){cout << iv[i] << " ";}cout << endl;return 0;
}

总结

  • STL的六大组件给软件带来了新的多态和复用,是现代C++语言高效的精髓
  • 泛型和STL的学习路线很陡,建议初学者先学会基本的使用和简单的扩展
  • 掌握了一定基础的情况下,可以通过进一步学习和分析源码,编写自己的组件来提升能力

C++多线程

  • C++11中thread的使用
  • mutex等锁的使用
  • 进程与线程,同步与异步
  • 线程交换与移动
#include <thread>
#include <mutex>
#include <iostream>
using namespace std;mutex g_mutex;
void T1()
{g_mutex.lock();cout << "T1 Hello" << endl;g_mutex.unlock();
}
void T2(const char* str)
{g_mutex.lock();cout << "T2 " << str << endl;g_mutex.unlock();
}
int main()
{thread t1(T1);thread t2(T2, "Hello World");t1.join();//t2.join();t2.detach();cout << "Main Hi" << endl;return 0;
}
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
// 存钱
void Deposit(mutex& m, int& money)
{// 锁的粒度尽可能的最小化for(int index = 0; index < 100; index++){m.lock();money += 1;m.unlock();}
}
// 取钱
void Withdraw(mutex& m, int& money)
{// 锁的粒度尽可能的最小化for (int index = 0; index < 100; index++){m.lock();money -= 2;m.unlock();}
}
int main()
{// 银行存取款//int money = 2000;//mutex m;//cout << "Current money is: " << money << endl;//thread t1(Deposit, ref(m), ref(money));//thread t2(Withdraw, ref(m), ref(money));//t1.join();//t2.join();//cout << "Finally money is: " << money << endl;//线程交换 //thread tW1([]()//{// cout << "ThreadSwap1 " << endl;//});//thread tW2([]()//{//    cout << "ThreadSwap2 " << endl;//});//cout << "ThreadSwap1' id is " << tW1.get_id() << endl;//cout << "ThreadSwap2' id is " << tW2.get_id() << endl;//cout << "Swap after:" << endl;//swap(tW1, tW2); //cout << "ThreadSwap1' id is " << tW1.get_id() << endl;//cout << "ThreadSwap2' id is " << tW2.get_id() << endl;//tW1.join();//tW2.join(); 线程移动thread tM1( []() { ; } );//tM1.join();cout << "ThreadMove1' id is " << tM1.get_id() << endl;cout << "Move after:" << endl;thread tM2 = move(tM1);cout << "ThreadMove2' id is " << tM2.get_id() << endl;cout << "ThreadMove1' id is " << tM1.get_id() << endl;tM2.join();return 0;
}

C++的编程思想和进阶编程相关推荐

  1. 如何建立编程思想和提高编程思想

    一.首先,什么是编程思想? 编程思想是一种指导思想,这个指导思想,将会诱发你如何写代码的行为. 如果理解这话的意思呢?打个比方,中华文明千百年在民众心中形成了一个"统一天下"的思想 ...

  2. java编程思想 入门_java编程思想学习(基础)

    第一章 java介绍 1.编程的本质: 机器空间:解空间 问题空间:实际需要解决的业务问题,将该问题抽象化,在解空间中对问题建模. 编程就是建立问题空间和机器空间中的关联 面向对象编程思想: 1.万物 ...

  3. java编程思想 文献_JAVA编程思想英文参考文献和翻译

    JAVA编程思想英文参考文献和翻译 时间:2016-11-15 14:44来源:毕业论文 虽然java是基于C++基础上的,但是它更是纯粹的面向对象语 "If we spoke a diff ...

  4. linux unix编程思想,Unix网络编程思想

    本次博客主要总结参考<Unix网络编程>卷一前四章的知识,对TCP一对一通信进行重新改造和分析,经典就是经典,无可替代! 一.为什么使用包裹函数 任何现实世界的程序都必须检查每个函数调用是 ...

  5. java面向对象编程思想_Java面向对象编程思想的理解

    1.我们总说java是一门面向对象编程的语言,那什么是面向对象呢? 我是这样理解的,对象是事物存在的实体,如,猪.狗,花早等都是对象,对象由两部分组成.面向对象编程的三大特点:继承,多态,类是封装对象 ...

  6. java 编程思想 笔记_java编程思想笔记20170215

    importjava.util.ArrayList;importjava.util.List;public classTest {public static voidmain(String[] arg ...

  7. java 编程思想 并发_java编程思想-java中的并发(一)

    一.基本的线程机制 并发编程使我们可以将程序划分为多个分离的.独立运行的任务.通过使用多线程机制,这些独立任务中的每一个都将由执行线程来驱动. 线程模型为编程带来了便利,它简化了在单一程序中同时jia ...

  8. JAVA编程思想.姊妹篇.JAVA编程讲义.第1章 Java开发入门

    1.1 Java概述 1.1.1 Java的由来与发展 Java是一种高级计算机语言,它是由Sun公司(2009年4月20日被Oracle公司收购,2010年完成合并)于1995年5月推出的一种用来编 ...

  9. java编程思想读书_JAVA编程思想读书记(一)

    JAVA是面向对象的语言,这一点每一个开发者都知道.但是享受于在myeclipse上自动生成,自动解决一切问题的时候,有些基础的我们也许会忘掉.我能明显感觉到自己对于软件的依赖以及基础知识的流失,所以 ...

最新文章

  1. Java获取系统日期时间
  2. java dfa_java 实现DFA 算法(理论百度搜索)
  3. 多位博士毕业去了三四流高校,现在怎么样了?
  4. Redis数据类型--字符串类型
  5. Oracle数据库管理›oracle内部的jdk版本
  6. element筛选 ajax,vue使用element Transfer 穿梭框实现ajax请求数据和自定义查询
  7. css 右上角 翻开动画_css制作电闪雷鸣的天气图标
  8. vscode 找不到path路径
  9. ionic4 富文本
  10. vue列表渲染中key的作用_vue中:key的作用
  11. ubuntu 怎么格式化U盘?(转载)
  12. Javascript特效:图片切换(类似于电商网站图片查看)的封装实现和闭包实现
  13. Android 滑动冲突问题的简单解决思路
  14. stm32之I2C编程前期准备
  15. 动易CMS从word复制粘贴公式
  16. trunk与access的区别
  17. plt的默认风格/样式设置 or 将plt.rcParams恢复恢复到默认参数设置
  18. 商品促销——策略模式
  19. 卫生事业单位计算机科学与技术,卫生事业单位考试计算机科学与技术学习知识点.docx...
  20. LoRa的码片速率chip rate

热门文章

  1. [Git]删除远程分支和本地分支
  2. 项目启动时报错,Maven Resources Compiler报错
  3. SQL教程——联合查询
  4. 给八千不干 “假乞丐”给八千不干不如装残疾人乞讨!【图文】
  5. layui 上传文件限制数量优化
  6. 数据流程图实例2——考务处理系统流程图
  7. On Device Debug!IDA+GDB trace automagic.apk in s1
  8. 阿里这么牛逼,Leader是如何带兵打仗的?
  9. SLAM中的零空间问题
  10. i386、x86-64(AMD64)区分