C++个人笔记(一)
来源:互联网 发布:jdk 8 linux x64.rpm 编辑:程序博客网 时间:2024/05/22 21:25
总结:
另有一篇文章 A*算法和代码:http://blog.csdn.net/lmnxjf/article/details/8917679
A*算法,寻找最优路线的高效方法。
目录
1 STL
2 二维数组动态分配内存
3 带模板参数的模板类
4 类型转换
5 小知识点
6 函数指针
7 逗号表达式
8 运行时类型转换
9 类里面的小知识点
10 建立动态链接库
个人笔记,记录一些基础,但是又经常用到的C++方法。 不断整理ing
1、 STL
(1) vector 迭代器的使用
vector<string> title(10);// 申请一个十个string的vector容器vector<string>::iterator p;// 声明一个迭代器p= title.begin();// 这是就可以对p取值, 累加cout<<*p++<<endl<<*p<<endl;//输出 title[0],title[1]
title.push_back() 它将元素添加到矢量末尾,此时title的容积增了1个元素。
验证代码:
int main(){vector<int > pp(100);vector<int>::iterator p;int i=0;for(p= pp.begin(); p!=pp.end(); p++){pp[i]=i;i++;}cout<<(pp.end()-pp.begin())<<endl;pp.push_back(12);pp.push_back(12);cout<<(pp.end()-pp.begin())<<endl;}
输出:
title.erase(title.begin(), tetle.begin()+2);// 擦除开始的两个元素(删除的元素为 [参数1, 参数2)即不删除参数2所指向的元素) 如果第一个参数 大于第二个参数,将不做删除。
vector 中自定义排序问题,random_shuffle 函数随机排列区间的元素, sort 按规则排序,通过自己定义函数返回bool量决定。代码中实现降序排序。
#include<iostream>#include <string>#include<vector>#include<algorithm>#include<iterator>using namespace std;void Dispaly(int p){cout<<p<<endl;}bool NewSort(int p,int q){if (p>q)return true;else return false;}void AddData(int& a){static int i=0;a=i;++i;}int main(){vector<int > pp(20);vector<int>::iterator p;//for(p= pp.begin(); p!=pp.end(); p++)//{//pp[i]=i;//i++;//}ostream_iterator<int, char> out_iter(cout,"\n");// \n为没输出一个元素后的分隔符 for_each(pp.begin(), pp.end(),AddData);random_shuffle(pp.begin(), pp.end());sort(pp.begin(), pp.end(), NewSort);//for_each(pp.begin(), pp.end(),Dispaly);copy(pp.begin(), pp.end(), out_iter);}(2) copy此处的作用是将数据复制到到显示器中, 模板ostream_iterator是输出迭代器概念的一个模型。需要包含头文件 iterator,out_iter迭代器现在是一个接口让你可以使用cout来显示信息。 模板中第一个参数(这里为int)指出了输出的数据类型,第二个参数(char)指出了输出使用字符类型。
通样输入也可以使用输入输出迭代器。 copy(istream_iterator<int, char>(cin), istream_iterator<int,char>(), pp.begin())// 作用从输入流中读取,知道文件结尾、类型不匹配或者出现错误为止。
reverse_iterator反向迭代器(目的是代码重用),例如 rbegin() 返回一个指向超尾的反向迭代器,rend()返回一个指向第一个元素的反向迭代器。copy(pp.rbegin, pp.rend(), out_iter);可以反向显示内容。 对rbegin()递增就是将导致它递减。
vector<int>::reverse_iterater reverp;
for(reverp=pp.rbegin; reberp!= pp.rend;++ reverp)
cout<<*reverp<<" ";
reverp= pp.rbegin(),指向超尾,rend()返回第一个元素的位置因此不能对其进行解除引用,反向指针通过先递减,再解除引用解决了这两个问题。
*注意:rbegin(), 和end() 返回一样的超尾值,但是类型不同。
int main(){string str[4]={"1","2","3","4"};string str1[2]={"one","two"};string str2[2]={"three","four"};vector<string> word(4);copy(str, str+4, word.begin());ostream_iterator<string, char>out(cout, " ");copy(word.begin(), word.end(), out);//back_inser_iteratorcout<<endl;copy(str1, str1+2, back_insert_iterator<vector<string>>(word));//在word 的尾部加copy(word.begin(), word.end(), out);cout<<endl;// insert_iteratorcopy(str2, str2+2,insert_iterator<vector<string>>(word, word.begin()+2));copy(word.begin(), word.end(), out);cout<<endl<<"down!"<<endl;}
输出:
小结: 迭代器就像指针,遍历整个容器可以使用 for(p=title.begin(); p!=title.end(); ++p。vector可以说是数据的类的表示,它提供自动内存管理功能,可以动态改变vector对象长度,并随着元素的添加和删除而增大和减小。在尾部添加和删除元素时间是固定的,但在头部或中间插入和删除元素时间复杂度为线性的。
2、 二维数组动态分配内存
int** erwei= (int**) new int[SIZE1];for(int i=0; i<SIZE1; i++){ erwei[i]= new int[SIZE2]; //*(erwei+1)= new int[SIZE2]}//释放内存for(int i=0; i<SIZE1;i++){ delete []erwei[i];}delete []erwei;
3 带模板参数的模板类
#include<iostream>using namespace std;template <class T>class Array{public:Array(){};Array( T i ):data_a( i ){}void Display(){cout<<"Arry display "<<endl;}private:T data_a;};//template<class T, template<class>class A>其中//class T 是模板B的第一个参数, 而template<class> class A//说明第二个参数是一个模板参数 也说明了类模板A是一个又一个参数的模板参数// 同样也可以写成 template<class T, template<class Q>class A>template<class T, template<class>class A>class B{public:B(){cout<<"construction of b: "<<endl;}void Display(){a.Display(); cout<<"B display: "<<endl;}private:T data_b;A<T> a;};int main(){Array<int> mya(3);B<int, Array> b;b.Display();}
假设要将一个int类型转换为double。在c标准中可以这样
int num1, num2;
double num3= ((bouble)num1)/ num2;
如果采用新的c++转换法:
double num3=static_cast<double>(num1)/num2;
而将一个const常量转换为一个变量应用const_cast.即可用const_cast去点对象的常量性。
# dynamic_cast,可以将base class objects的pointers或references转换为 指向derived class objects的pointers 或 references.
Widget *pw;
...
update(dynamic_cast<SpecialWidget*>pw); 将pw指向的widget转换为派生类的specialwidget。
int* p = new int(0);auto_ptr<int> ap1(p);auto_ptr<int> ap2(p);//因为ap1与ap2都认为指针p是归它管的,在析构时都试图删除p, 两次删除同一个对象的行为在C++标准中是未定义的。所以我们必须防止这样使用au//to_ptr.
~A{try{// 可能依法异常的操作}catch(...)//catch中什么也不做 就是不让异常跑出到析构函数的外面{}}
异常跑出的都是参数的副本,以为在函数中异常跑出时,这个函数已经失去了控制权,所以这个函数中的变量也就没有存在的意义了,因此必须使用参数的副本。
catch(Widget& w){...throw;}catch(Widget& w){...throw w;}这两个catch的唯一区别就是,前者抛出的是当前的exception, 后者跑出的是当前exception的副本。 一般使用throw抛出当前异常原因之一就是没有复制行为,速度更快。
# 异常捕捉中部存在隐式转换, 这和函数调用时有区别的。
try{int value;if(fountion())throw value;}catch(double b){...}
#include<iostream>using namespace std;typedef void (*CallBackPtr)(int x, int y,int data);void display(int x, int y,int data){cout<<"x "<<x<<" y "<<y<<" data "<<data<<endl;}int main(){CallBackPtr pcall;pcall=display;//f好乐迪封建礼教pcall(2,4, 5);}
逗号表达式的形式如下:
表达式1,表达式2,表达式3,...... ,表达式n
逗号表达式的要领:
(1) 逗号表达式的运算过程为:从左往右逐个计算表达式。
(2) 逗号表达式作为一个整体,它的值为最后一个表达式(也即表达式n)的值。
(3) 逗号运算符的优先级别在所有运算符中最低。
#include<iostream>#include<vector>using namespace std;class Security{protected:enum{ BASEID = 0};public:virtual ~Security(){};virtual bool IsA(int id) {return id == BASEID;}};class Stock: public Security{typedef Security Super;protected:enum {OFFSET =1,TYPEID = OFFSET + BASEID};public:virtual bool IsA(int id) {return id == TYPEID || Super::IsA(id);}static Stock* dynacast(Super* s){return (s->IsA(TYPEID))? static_cast<Stock*>(s) : 0;}};class Bond: public Security{typedef Security Super;protected:enum {OFFSET =2,TYPEID = OFFSET + BASEID};public:virtual bool IsA(int id) {return id == TYPEID || Super::IsA(id);}static Bond* dynacast(Super* s){return (s->IsA(TYPEID))? static_cast<Bond*>(s) : 0;}};class Investment: public Security{typedef Security Super;protected:enum {OFFSET =3,TYPEID = OFFSET + BASEID};public:virtual bool IsA(int id) {return id == TYPEID || Super::IsA(id);}static Investment* dynacast(Super* s){return (s->IsA(TYPEID))? static_cast<Investment*>(s) : 0;}void Special(){cout<<"special investment function"<<endl;}};class Metal: public Investment{typedef Security Super;protected:enum {OFFSET =4,TYPEID = OFFSET + BASEID};public:virtual bool IsA(int id) {return id == TYPEID || Super::IsA(id);}static Metal* dynacast(Super* s){return (s->IsA(TYPEID))? static_cast<Metal*>(s) : 0;}};int main(){vector<Security*> portfolio;portfolio.push_back(new Metal);portfolio.push_back(new Investment);portfolio.push_back(new Bond);portfolio.push_back(new Stock);portfolio.push_back(new Security);for (vector<Security*>::iterator it = portfolio.begin(); it!= portfolio.end(); ++it){Investment* cm = Investment::dynacast(*it);if (cm){cm->Special();}elsecout<<"not an Investment"<<endl;}cout<<"cast from intermediate pointer:"<<endl;Security* sp =new Metal;Investment* cp = Investment::dynacast(sp);if (cp){cout<<"it is Investment"<<endl;}Metal* mp = Metal::dynacast(sp);if (mp){cout<<"is is Metal"<<endl;}cout<<typeid(sp).name()<<endl; cout<<typeid(cp).name()<<endl; cout<<typeid(*sp).name()<<endl;}
查看动态链接库中导出的函数, 可以在命令行中先到工程目录, 使用vc提供的,dumpbin XX.dll 来查看
//extern int add(int a, int b);//extern int substract(int a, int b);_declspec(dllimport) int add(int a , int b);_declspec(dllimport) int substract(int a, int b);用extern声明表明其是在外部定义的函数, 而利用_declspec(dllimport) 表明其在动态链接库中, 这时编译器可以生产更加高效的代码,所以一般使用_declspec(dllimport)来导入函数。
_declspec(dllimport) int add(int a, int b);_declspec(dllimport) int substract(int a, int b);import表明函数是从动态链接库中导入的。
//mydll.h#ifdef MYDLL_API#else#define MYDLL_API _declspec(dllimport)#endifMYDLL_API int add(int a, int b);MYDLL_API int substract(int a, int b);//其中 若将注释去掉,则说明导出的是整个类 class /*MYDLL_API*/ Point{private:int m_a;int m_b;public:Point(int a=0, int b=0):m_a(a), m_b(b){};MYDLL_API void OutPut() const;};
.cpp
#define MYDLL_API _declspec(dllexport)#include"mydll.h"#include<iostream>int add(int a, int b){return a+b;}int substract(int a, int b){return a-b;}void Point::OutPut()const{using std::cout;using std::endl;cout<<"m_a "<< m_a<<",m_b "<<m_b<<endl;}extern "C" _declspec(dllexport) 加入 extern“C”后是一C标准导出函数,即函数名不发生改变。 add导出的函数名还是 add,但是这个方法只能用于导出全局函数,不能用于导出类的成员函数。
#自定义导出函数的格式,可以在工程中新建一个txt文档,将后缀改为.def,文件名改成工程文件名(不是必需的)。在.def文件中添加要导出函数的名字
EXPORTS
add @1
substract @2
display @3
#include<iostream>#include<Windows.h>//#include"..\..\MyDll\MyDll\mydll.h"//#pragma comment( lib, "..\\debug\\libTest.lib" ) //指定与静态库一起连接using namespace std;//extern int add(int a, int b);//extern int substract(int a, int b);//_declspec(dllimport) int add(int a , int b);//_declspec(dllimport) int substract(int a, int b);int main(){HINSTANCE hInst;hInst = LoadLibrary("MyDll2.dll");typedef int (*ADDPROC)(int a, int b);ADDPROC Add = (ADDPROC)GetProcAddress(hInst, MAKEINTRESOURCE(1));ADDPROC Substract = (ADDPROC)GetProcAddress(hInst, "substract");int sum= Add(2,4);int sub = Substract( 4, 3);cout<<sum<<endl<<sub<<endl;FreeLibrary(hInst);}
- 个人学习笔记(一)
- C++个人笔记(一)
- Disruptor个人笔记(一)
- C个人笔记
- 个人C语言笔记
- JSON学习个人笔记(一)
- OpenMp 个人笔记(一)
- Python个人学习笔记一
- 个人Linux 学习笔记一
- 个人学习笔记(一)
- GitHub基础教程(一) 个人笔记
- Makefile个人学习笔记一
- 学习android个人笔记一
- C语言个人学习笔记
- 个人的C语言笔记
- C语言学习个人笔记
- 《C与指针》个人笔记
- C\C++ 程序员从零开始学习Android - 个人学习笔记(一) - 计划和书籍
- 书籍记录
- C#调用cmd执行ftp命令
- mysql主从同步详解
- 线上应用故障排查之一:高CPU占用(转)
- 《程序员的第一年》---------- 读写配置文件---Properties.Settings.
- C++个人笔记(一)
- 通用型有源滤波器(universal active filter)
- 应届生求职必备:常用的16个c/c++面试题
- iPhone ARC 宏定义
- FileUtils
- VMware.Workstation Linux与windows实现文件夹共享
- ios 内存管理原则及exec_back_assess调试
- 总算解决了swfupload在非IE(chrome firefox opera)统统不能用的问题
- FusionCharts等产品简介