test.cpp 定义控制台应用程序的入口点
class CopyTest
{
private:
string name;
int id;
public:
copyTest(int i,string n):id(1),name(n)
{}
~CopyTest()
{}
----------------------------
CopyTest& operator = (const CopyTest& e)
{
name = e.name;
id = e.id;
return *this;
}
----------------------------
void Display()
{
cout<<name<<""id<<endl;
}
}
=================================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
=================================================
operator=返回一个本对象的引用
关于operator=函数的返回值,我们的返回值类型是对象本身的引用,
return时使用的是this指针所指的位置的内容(即*this的值)
a=b=c
//相当于
a=(b=c)
即所谓的连锁赋值,赋值操作符必须返回一个reference指向操作符的左侧实参
注意,这种操作在赋值操作中都成立
CopyTest& operator=(const CopyTest& e)
{
return *this
}
======================================================
》》》》》》》》》》》》》》》》》》》》》》》》》》》》
======================================================
深拷贝浅拷贝
在拷贝构造函数中相同,operator=重载中也含有深拷贝与浅拷贝的概念。
class CopyTest
{
string name;
int id;
int* pointer;
CopyTest(int i,string n,int* p):id(i),name(n),pointer(p)
{}
CopyTest& operator = (const CopyTest& e)
{
name=e.name;
id=e.id;
delete pointer;
pointer=new int(*e.pointer);
}
void Display()
{
count<<"name:"<<name<<"pointer"<<*pointer<<endl
}
}
int _tmain(int argc,_TCHAR* argv[])
{
CopyTest test1(1,"hehe",new int(1));
CopyTest test2(2,"haha",new int(2));
}
=================================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
=================================================
int* p = new int[3];
int *p = new int(10);
===============================
int *p= new int(10);
cout<<*p<<endl
===============================
a) int a;表示一个内存空间,这个空间用来存放一个整数(int);
b) int* a;表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个存放整数的空间,即a)中提到的空间;
c) int** a;表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个存放指针的空间,并且指向的这个空间中的指针,指向一个整数。也简单的说,指向了一个b)中提到的空间;
d) int (*a)[10];表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个长度为10、类型为int的数组;和int** a的区别在于,++、+=1之后的结果不一样,其他用法基本相同。以上四种类型见上图表示。
e) int (*a)(int);表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个函数,这个函数有一个类型为int的参数,并且函数的返回类型也是int。
================================>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
================================>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
C++的STL的关联容器multimap允许一个key值对应多个值,当对整个multimap进行遍历
时可以使用迭代器。
====================================================================》
本文包括两个大的异常实现概念:C++的标准异常和SEH异常
C++标准异常
很高兴看到错误之后的Heap/stack中对象被释放,可是如果没有呢
又或者试想一下一个能解决的错误,需要我们把整个程序kill掉吗
SHE异常
SEH是window的结构化异常,每一个win32程序员都应该要掌握它
SEH功能强大,包括Termination handing和exception handling 两部分
在SEH中有大量的代码,已经在win平台上测试过了
这里要测试一下:在__finally处理中编译器参与了绝大多数的工作,
而EXception则是OS接管了几乎所有工作
对__finally来说当遇到ExitThread/ExitProcess/abort等函数时,
finally块不会被执行
关于异常的高级使用,有以下内容是没有完成了:
使用构造函数防止资源Leak
禁止异常信息传递到析构function外
通过引用捕获异常
谨慎使用异常规格
了解异常处理造成的系统开销
限制对象数量
灵巧指针
================================================》
================================================》
资源泄漏和内存泄漏
=================================================》
什么是资源,句柄,对象,文件,内存等都是资源
进程申请的内存,只要没释放,且进程没有终止,那么这个内存就是
属于进程的。
内存有两种方式,一个是堆一个是栈
栈就是每个线程的栈,栈用于传递参数,用保存自动变量。
自动变量就是栈自动管理的,超出变量的作用域,这些变量所占的
内存就会被释放
线程栈是一个先进先出的结构,程序中的函数调用,就会将函数中的局部
变量和参数都压入栈中,这样可以很方便的传递参数,当函数执行完毕,
即返回调用函数,那么之前压栈的变量都要出栈
所谓的自动变量的作用域就是起于压栈,终于出栈
===========================================》
数据结构的栈和堆
栈就像装数据的桶或箱子
堆像一个倒过来的树
============================================》
1,栈区:类似于数据结构中的栈
2,堆区:分配方式倒是类似于链表
3,全局区(静态区)
4,文字常量区
5,程序代码区
===============================================》
说到链表之前,先说一下线性表。
线性表有两种存储方式:
一种是顺序存储结构
一种是链式存储结构
顺序结构:
查询的时间复杂度是o(1)
插入和删除的时间复杂度最坏能达到o(n)
链式存储结构哦就是两个相邻的元素在内存中可能不是相邻的
插入和删除的时间复杂度o(1)
访问的最坏时间复杂度为o(n)
template<class T>
class slistNode
{
public:
slistNode(){next=NULL;}
T data;
slistNode* next;
}
第二步:写单链表类的声明,包括属性和方法
template<class T>
class myslist
{
private:
unsigned int listlength;
slistNode<T>* node;//临时节点
slistNode<T>* lastnode;//头结点
slistNode<T>* headnode;//尾节点
public:
myslist();//初始化
unsigned int length();//链表元素的个数
void add(T x);//表尾添加元素
void traversal();//遍历整个链表并打印
bool isEmpty();//判断链表是否为空
slistNode<T>* find(T x);//查找第一个值为x的节点,返回节点的地址,找不到返回NULL
void Delete(T x);//删除第一个值为x的节点
void insert(T x,slistNode<T>* p);//在p节点后插入值为x的节点
void insertHead(T x);//在链表的头部插入节点
};
第三步:写构造函数,初始化链表类的属性
template<class T>
myslist<T>::myslist()
{
node=NULL;
lastnode=NULL;
headnode=NULL;
listlength=0;
}
第四步:实现add方法
template<class T>
void myslist<T>::add(T x)
{
node=new slistNode<T>();//申请一个新的节点
node->data=x;//新节点赋值为x
if(lastnode==NULL)//如果没有尾节点则链表为空,node既为头结点,又是尾节点
{
headnode=node;
lastnode=node;
}
else//如果链表非空
{
lastnode->next=node;//node既为尾节点的下一个节点
lastnode=node;//node变成了尾节点,把尾节点赋值为node
}
++listlength;//元素个数+1
}
第五步:实现traversal()函数,遍历并输出节点信息
template<class T>
void myslist<T>::traversal()
{
node=headnode;//用临时节点指向头结点
while(node!=NULL)//遍历链表并输出
{
cout<<node->data<<ends;
node=node->next;
}
cout<<endl;
}
===================================================》
》》》》》》》》》》》》》》》》》》》》》》》》》》》
===================================================》
要维护消息队列,STL有两种容器胜任此项工作
分别是list和deque
list是基于链表实现的,deque是基于动态数组实现的
测试的类型fuck定义如下:
struct fuck{
int a,b,c;
}
测试1:容器大小为十万个fuck,循环进行pop_back()和push_front()操作
int main()
{
}
==========================================================
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
==========================================================
C++有两种类型的容器:顺序容器和关连容器
顺序容器主要有vector,list,deque
vector表示一段连续的内存地址,基于数组的实现
list基于链表实现
deque与vector类似,但是对于首元素提供删除和插入的双向支持
std::deque( double-ended queue ,双端队列)
std::queue(队列是一种特殊的线性表,是一种先进先出(FIFO)的数据结构)
set,multiset,map,multimap底层数据结构为红黑树
int _tmain(int argc ,_TCHAR* argv[])
{
CopyTest test1(1,"heheh");
CopyTest test2(2,"hahah");
test2.Display();
test2=test1;
test1.Dispaly();
return 0 ;
}
class CopyTest
{
private:
string name;
int id;
public:
copyTest(int i,string n):id(1),name(n)
{}
~CopyTest()
{}
----------------------------
CopyTest& operator = (const CopyTest& e)
{
name = e.name;
id = e.id;
return *this;
}
----------------------------
void Display()
{
cout<<name<<""id<<endl;
}
}
=================================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
=================================================
operator=返回一个本对象的引用
关于operator=函数的返回值,我们的返回值类型是对象本身的引用,
return时使用的是this指针所指的位置的内容(即*this的值)
a=b=c
//相当于
a=(b=c)
即所谓的连锁赋值,赋值操作符必须返回一个reference指向操作符的左侧实参
注意,这种操作在赋值操作中都成立
CopyTest& operator=(const CopyTest& e)
{
return *this
}
======================================================
》》》》》》》》》》》》》》》》》》》》》》》》》》》》
======================================================
深拷贝浅拷贝
在拷贝构造函数中相同,operator=重载中也含有深拷贝与浅拷贝的概念。
class CopyTest
{
string name;
int id;
int* pointer;
CopyTest(int i,string n,int* p):id(i),name(n),pointer(p)
{}
CopyTest& operator = (const CopyTest& e)
{
name=e.name;
id=e.id;
delete pointer;
pointer=new int(*e.pointer);
}
void Display()
{
count<<"name:"<<name<<"pointer"<<*pointer<<endl
}
}
int _tmain(int argc,_TCHAR* argv[])
{
CopyTest test1(1,"hehe",new int(1));
CopyTest test2(2,"haha",new int(2));
}
=================================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
=================================================
int* p = new int[3];
int *p = new int(10);
===============================
int *p= new int(10);
cout<<*p<<endl
===============================
a) int a;表示一个内存空间,这个空间用来存放一个整数(int);
b) int* a;表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个存放整数的空间,即a)中提到的空间;
c) int** a;表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个存放指针的空间,并且指向的这个空间中的指针,指向一个整数。也简单的说,指向了一个b)中提到的空间;
d) int (*a)[10];表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个长度为10、类型为int的数组;和int** a的区别在于,++、+=1之后的结果不一样,其他用法基本相同。以上四种类型见上图表示。
e) int (*a)(int);表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个函数,这个函数有一个类型为int的参数,并且函数的返回类型也是int。
================================>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
================================>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
C++的STL的关联容器multimap允许一个key值对应多个值,当对整个multimap进行遍历
时可以使用迭代器。
====================================================================》
本文包括两个大的异常实现概念:C++的标准异常和SEH异常
C++标准异常
很高兴看到错误之后的Heap/stack中对象被释放,可是如果没有呢
又或者试想一下一个能解决的错误,需要我们把整个程序kill掉吗
SHE异常
SEH是window的结构化异常,每一个win32程序员都应该要掌握它
SEH功能强大,包括Termination handing和exception handling 两部分
在SEH中有大量的代码,已经在win平台上测试过了
这里要测试一下:在__finally处理中编译器参与了绝大多数的工作,
而EXception则是OS接管了几乎所有工作
对__finally来说当遇到ExitThread/ExitProcess/abort等函数时,
finally块不会被执行
关于异常的高级使用,有以下内容是没有完成了:
使用构造函数防止资源Leak
禁止异常信息传递到析构function外
通过引用捕获异常
谨慎使用异常规格
了解异常处理造成的系统开销
限制对象数量
灵巧指针
================================================》
================================================》
资源泄漏和内存泄漏
=================================================》
什么是资源,句柄,对象,文件,内存等都是资源
进程申请的内存,只要没释放,且进程没有终止,那么这个内存就是
属于进程的。
内存有两种方式,一个是堆一个是栈
栈就是每个线程的栈,栈用于传递参数,用保存自动变量。
自动变量就是栈自动管理的,超出变量的作用域,这些变量所占的
内存就会被释放
线程栈是一个先进先出的结构,程序中的函数调用,就会将函数中的局部
变量和参数都压入栈中,这样可以很方便的传递参数,当函数执行完毕,
即返回调用函数,那么之前压栈的变量都要出栈
所谓的自动变量的作用域就是起于压栈,终于出栈
===========================================》
数据结构的栈和堆
栈就像装数据的桶或箱子
堆像一个倒过来的树
============================================》
1,栈区:类似于数据结构中的栈
2,堆区:分配方式倒是类似于链表
3,全局区(静态区)
4,文字常量区
5,程序代码区
===============================================》
说到链表之前,先说一下线性表。
线性表有两种存储方式:
一种是顺序存储结构
一种是链式存储结构
顺序结构:
查询的时间复杂度是o(1)
插入和删除的时间复杂度最坏能达到o(n)
链式存储结构哦就是两个相邻的元素在内存中可能不是相邻的
插入和删除的时间复杂度o(1)
访问的最坏时间复杂度为o(n)
template<class T>
class slistNode
{
public:
slistNode(){next=NULL;}
T data;
slistNode* next;
}
第二步:写单链表类的声明,包括属性和方法
template<class T>
class myslist
{
private:
unsigned int listlength;
slistNode<T>* node;//临时节点
slistNode<T>* lastnode;//头结点
slistNode<T>* headnode;//尾节点
public:
myslist();//初始化
unsigned int length();//链表元素的个数
void add(T x);//表尾添加元素
void traversal();//遍历整个链表并打印
bool isEmpty();//判断链表是否为空
slistNode<T>* find(T x);//查找第一个值为x的节点,返回节点的地址,找不到返回NULL
void Delete(T x);//删除第一个值为x的节点
void insert(T x,slistNode<T>* p);//在p节点后插入值为x的节点
void insertHead(T x);//在链表的头部插入节点
};
第三步:写构造函数,初始化链表类的属性
template<class T>
myslist<T>::myslist()
{
node=NULL;
lastnode=NULL;
headnode=NULL;
listlength=0;
}
第四步:实现add方法
template<class T>
void myslist<T>::add(T x)
{
node=new slistNode<T>();//申请一个新的节点
node->data=x;//新节点赋值为x
if(lastnode==NULL)//如果没有尾节点则链表为空,node既为头结点,又是尾节点
{
headnode=node;
lastnode=node;
}
else//如果链表非空
{
lastnode->next=node;//node既为尾节点的下一个节点
lastnode=node;//node变成了尾节点,把尾节点赋值为node
}
++listlength;//元素个数+1
}
第五步:实现traversal()函数,遍历并输出节点信息
template<class T>
void myslist<T>::traversal()
{
node=headnode;//用临时节点指向头结点
while(node!=NULL)//遍历链表并输出
{
cout<<node->data<<ends;
node=node->next;
}
cout<<endl;
}
===================================================》
》》》》》》》》》》》》》》》》》》》》》》》》》》》
===================================================》
要维护消息队列,STL有两种容器胜任此项工作
分别是list和deque
list是基于链表实现的,deque是基于动态数组实现的
测试的类型fuck定义如下:
struct fuck{
int a,b,c;
}
测试1:容器大小为十万个fuck,循环进行pop_back()和push_front()操作
int main()
{
}
==========================================================
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
==========================================================
C++有两种类型的容器:顺序容器和关连容器
顺序容器主要有vector,list,deque
vector表示一段连续的内存地址,基于数组的实现
list基于链表实现
deque与vector类似,但是对于首元素提供删除和插入的双向支持
std::deque( double-ended queue ,双端队列)
std::queue(队列是一种特殊的线性表,是一种先进先出(FIFO)的数据结构)
set,multiset,map,multimap底层数据结构为红黑树
int _tmain(int argc ,_TCHAR* argv[])
{
CopyTest test1(1,"heheh");
CopyTest test2(2,"hahah");
test2.Display();
test2=test1;
test1.Dispaly();
return 0 ;
}