***************************************************************************************
01--
//宏定义
#define
STR(
a) #a
#define
CAT(
a,
b)
a##b
int
xy = 100;
cout <<
STR (ABCD) <<
endl;
cout <<
CAT (
x,
y) <<
endl;
***************************************************************************************
02--
#pragma pack(4) --定义结构体对齐自己为4字节
struct Test
{
char a;
double b;
char c;
}
#pragma pack()
***************************************************************************************
03--
C++ 中增加的作用域标识符::
用于对与局部变量同名的全局变量进行访问
用于表示类的成员
int
main(
void)
{
int*
p =
new
int;
int*
p =
new
int(33);
cout << *
p <<
endl;
int*
p2 =
new
int[10];
delete
p;
delete[]
p2;
}
operator
new 只分配内存
placement
new 不分配内存,调用拷贝构造函数
new
operator 分配内存 + 调用构造函数
extern
"C"
void fun(
int
a) 表示不进行名字改编-- 可以让C语言函数调用C++函数
new 一个新对象
内存分配(operator new)
调用构造函数
delete释放一个对象
调用析构函数
释放内存(operator delete)
***************************************************************************************
04--
//引用作为函数返回值
int
a[] = { 0, 1, 2, 3, 4 };
int&
index(
int
i)
{
return
a[
i];
}
int
main(
void)
{
index(3) = 100;
cout <<
"a[3]=" <<
a[3] <<
endl;
//引用作为函数返回值,使得函数可以放到赋值运算符左边
return 0;
}
***************************************************************************************
05--类型转换
类型转换--新式转型
const_cast<T>(expr)
static_cast<T>(expr)
reinterpret_cast<T>(expr)
dynamic_cast<T>(expr)
q用来移除对象的常量性(cast away the constness)
-
const_cast一般用于指针或者引用
-
使用const_cast去除const限定的目的不是为了修改它的内容
-
使用const_cast去除const限定,通常是为了函数能够接受这个实际参数
q编译器隐式执行的任何类型转换都可以由static_cast完成
-
当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换。
-
可以将void*指针转换为某一类型的指针
-
可以将基类指针指向派生类指针
-
无法将const转化为nonconst,这个只有const_cast才可以办得到
qreinterpret_cast “通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。
***************************************************************************************
12--
//等号运算符重载
Test& operator = (const Test& other);
explicit
***************************************************************************************
13--
构造函数初始化列表进行初始化
Clock::Clock(int hour,int minute ,int second):hour_(hour),minute_(minute),second_(second)
{
}
---------------------------------------------------------------
***************************************************************************************
14--
// 拷贝构造函数初始化列表
Test:: Test(const Test& other) : num_(other.num_)
{
}
***************************************************************************************
15--深拷贝浅拷贝 --运算符重载
class String
{
public:
String(char* str="");
~String();
//重写拷贝构造函数来实现深拷贝
String(const String& other);
//等号运算符重载
String& operator=(const String& other);
}
String::String(const String& other)
{
int len = strlen(other.str_) + 1;
str_ = new char[len];
memset(str_, 0, len);
strcpy(str_,other.str_);
}
String& String::operator=(const String& other)
{
if(this == &other)
return *this;
delete[] str_;
str_ = AllocAndCpy(other.str_);
return *this;
}
char* String::AllocAndCpy(char* str)
{
int len = strlen(str) + 1;
char* tmp = new char[len];
memset(tmp, 0, len);
strcpy(tmp,other.str);
return tmp;
}
------------------------------------------
空类默认产生的成员
class Empty {};
Empty(); // 默认构造函数
Empty( constEmpty& ); // 默认拷贝构造函数
~Empty(); // 默认析构函数
Empty& operator=( constEmpty& ); // 默认赋值运算符
Empty* operator&(); // 取址运算符
constEmpty* operator&() const; // 取址运算符 const
***************************************************************************************
16--
qstatic成员函数没有this指针
-
非静态成员函数可以访问静态成员
-
静态成员函数不可以访问非静态成员
***************************************************************************************
18--单例模式
***************************************************************************************
19--
q如果把一个对象指定为const,就是告诉编译器不要修改它
-
const对象的定义:
-
const 类名 对象名 ( 参数表 );
-
const对象不能调用非const成员函数
-
用mutable修饰的数据成员即使在const对象或在const成员函数中都可以被修改
***************************************************************************************
22--运算符重载
运算符重载的规则
-
运算符重载不允许发明新的运算符。
-
不能改变运算符操作对象的个数。
-
运算符被重载后,其优先级和结合性不会改变。
-
不能重载的运算符:
运算符 符号
作用域解析运算符 ::
条件运算符 ?:
直接成员访问运算符 .
类成员指针引用的运算符 .*
sizeof运算符 sizeof
q一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
q以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
q类型转换运算符只能以成员函数方式重载
q流运算符只能以友元的方式重载
***************************************************************************************
25--
void* operator new(
size_t
size)
void
operator
delete(
void*
p)
void
operator
delete(
void*
p,
size_t
size)
void*
operator
new(
size_t
size,
const
char*
file,
long
line)
void
operator
delete(
void*
p,
const
char*
file,
long
line)
void*
operator
new[](
size_t
size)
void
operator
delete[](
void*
p)
void
operator
delete[](
void*
p,
size_t
size)
**************************************************************************************
36--
动态指针 typedef void* (*CREATE_FUNC)( );
解决多重包含引起的多次定义问题
_declspec(selectany)
_attribute((weak)) //g++
***************************************************************************************
45--
if(isalpha(buf_[curPos_])||buf_[curPos_) =='_') //如果以字母或者_开头
***************************************************************************************
50-- setjmp longjmp 51-- set_terminate 函数指定终止函数
***************************************************************************************
58--单例模式
#include
<iostream>
#include
<memory>
using
namespace
std ;
class
Singleton
{
public:
static
Singleton*
GetInstance()
{
/*if (instance_ == NULL)
{
instance_ = new Singleton;
}
return instance_;*/
if (!
instance_.
get())
{
instance_ =
auto_ptr<
Singleton>(
new
Singleton);
}
return
instance_.
get();
}
~
Singleton()
{
cout <<
"~Singleton..." <<
endl;
}
private:
//拷贝构造函数
Singleton(
const
Singleton&
other);
//重载运算符
Singleton& operator=(
const
Singleton&
other);
Singleton()
{
cout <<
"Singleton..." <<
endl;
}
//智能指针
static
auto_ptr<
Singleton>
instance_;
};
auto_ptr<
Singleton >
Singleton ::
instance_ ;
int
main(
void)
{
Singleton*
s1 =
Singleton::
GetInstance();
Singleton*
s2 =
Singleton::
GetInstance();
return 0;
}
***************************************************************************************
#include
<iostream>
using
namespace
std;
//宏模拟 sizeof
#define
sizeof_v(
x) (
char*)(&
x+1)-(
char*)(&
x)
#define
sizeof_t(
t) ((
size_t)((
t*)0+1))
//对齐
#define
ALIGN(v,
b) ((v+
b-1)& ~(
b-1))
class
Empty
{
};
int
main(
void)
{
Empty
e;
int
n;
cout <<
sizeof(
e) <<
endl;
cout <<
sizeof(
Empty) <<
endl;
cout <<
sizeof_v(
e) <<
endl;
cout <<
sizeof_v(
n) <<
endl;
cout <<
sizeof_t(
Empty) <<
endl;
cout <<
sizeof_t(
int) <<
endl;
}
***************************************************************************************
59--IO
***************************************************************************************
write操作
write(buf,len)
write()返回一个ostream对象的引用
cout.write(buf,len) //char buf[len]
put()操作
输出单个字符
返回一个ostream对象的引用
cout.put('H').put('i');
istream流的操作
opeartor>>操作
get()
getline()
read()
peek()
putback()
get()操作
读取单个字符
返回一个整数
字符的ASCII吗
get对回车换行的处理
geta(char&)操作
读取单个字符
返回一个istream对象的引用
getline()操作符
char string1[256]
cin.getline(string1,256); //获取整行
cin >> string1; //遇到空白字符就停止
read(buf,len)
返回一个istream对象的引用
对空白字符照读不误
char buf[10] = {0};
cin.read(buf,5);
cout<<buf<<endl;
peek:查看而不读取
putback:将一个字符添加到流
***************************************************************************************
60--io --file
void open(const char *filename,int mode = ios::out,int prot = _SH_DENYNO);
#include
<iostream>
#include
<fstream>
using
namespace
std;
int
main(
void)
{
ofstream
fout;
fout.
open(
"test.txt");
//fout.open("test.txt",ios::out);;
if (
fout.
is_open())
//if(fout.good()) if(fout)
{
cout <<
"success" <<
endl;
}
else{
cout <<
"failed" <<
endl;
}
//assert(fout);
fout.
close();
return 0;
}
***************************************************************************************
打开方式/描述
ios::in 打开一个供读取的文件(ifstream流的默认值)
ios::out 打开一个供写入的文件(ofstream流的默认值)
ios::app 在写之前找到文件尾
ios::ate 打开文件后立即将文件定位在文件尾
-
ios::trunc 废弃当前文件内容
ios::nocreate(已不再支持) 如果要打开的文件并不存在,那么以此参数调用open()函数
ios::noreplace(已不再支持) 如果要打开的文件已存在,试图用open()函数打开时将返回一个错误
ios::binary 以二进制形式打开一个文件,默认是文本文件
#define_SH_DENYRW 0x10 /*deny read/write mode*/ 拒绝对文件进行读写
#define_SH_DENYWR 0x20 /*deny write mode */ 拒绝写入文件
#define_SH_DENYRD 0x30 /*deny read mode */ 拒绝文件读取权限
#define_SH_DENYNO 0x40 /*deny none mode */ 读取和写入许可
#define_SH_SECURE 0x_80 /*secure mode */ 共享读取,独占写入
从效果上看ofstream指定out模式等同于指定了out和trunc模式
默认情况下,fstream对象以in和out模式同时打开
当文件同时以in和out打开时不会清空
如果只使用out模式,而不指定in模式,则文件会清空现有数据
如果同时制定了out与app,不会清空
如果打开文件时指定了trunc模式,则无论是是否同时指定了in模式,文件同样会被清空
***************************************************************************************
61
int
main(
void)
{
ofstream
fout;
fout.
open(
"test.txt",
ios::
out|
ios::
binary);
char
ch;
for (
int
i = 0;
i < 26;
i++)
{
ch =
'A' +
i;
fout.
put(
ch);
}
fout.
close();
return 0;
}
如果以文本打开文件,写入字符是时候,遇到\n会作转换
写入\r不作转换
windows平台\n转换 \r\n
linux 平台保留不变
mac系统 \n 转换为\r
如果以二进制方式打开文件写入字符的时候,遇到\n 不会作转换
以文本方式打开文件,也可以写入二进制数据
以二进制方式打开文件,也可以写入文件
写入的数据是二进制还是文本,与打开方式无关,与写入使用的函数有关
要写入二进制数据,应该用write,相应的读要用read
***************************************************************************************
结构体的写入和读取
#include
<iostream>
#include
<fstream>
#include
<string>
using
namespace
std;
struct
Test
{
int
a;
string
b;
string
c;
};
int
main(
void)
{
Test
t1;
t1.
a = 100;
t1.
b =
"abcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
t1.
c =
"yyybbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
ofstream
fout(
"test.txt",
ios::
out |
ios::
binary);
//fout.write((char*)&t1, sizeof(t1));不能直接写入结构体实例,不可正常运行
fout.
write((
char*)&
t1.
a,
sizeof(
int));
int
len;
len =
t1.
b.
length();
fout.
write((
char*)&
len,
sizeof(
int));
fout.
write(
t1.
b.
data(),
t1.
b.
length());
len =
t1.
c.
length();
fout.
write((
char*)&
len,
sizeof(
int));
fout.
write(
t1.
c.
data(),
t1.
c.
length());
fout.
close();
ifstream
fin(
"test.txt",
ios::
in |
ios::
binary);
Test
t2;
//fin.read((char*)&t2, sizeof(Test));
fin.
read((
char*)&
t2.
a,
sizeof(
int));
fin.
read((
char*)&
len,
sizeof(
int));
t2.
b.
resize(
len);
fin.
read(&
t2.
b[0],
len);
fin.
read((
char*)&
len,
sizeof(
int));
t2.
c.
resize(
len);
fin.
read(&
t2.
c[0],
len);
cout <<
t2.
a <<
" " <<
t2.
b <<
" "<<
t2.
c<<
endl;
fin.
close();
return 0;
}
***************************************************************************************
文件流
#include
<iostream>
#include
<fstream>
#include
<string>
#include
<cassert>
using
namespace
std;
int
main(
void)
{
//文件的随机读写 seekp: seekg:
//seekp:设置输出文件流的文件指针位置
//seekg:设置输入文件流的文件指针位置
//tellp:获取输出文件的文件流的当前位置,以字节为单位
//tellg:获取输入文件的文件流的当前位置,以字节为单位
ifstream
fin(
"test.txt");
assert(
fin);
fin.
seekg(2);
char
ch;
fin.
get(
ch);
cout <<
ch <<
endl;
fin.
seekg(-1,
ios::
end);
fin.
get(
ch);
cout <<
ch <<
endl;
fin.
seekg(0,
ios::
end);
streampos
pos =
fin.
tellg();
//获取文件末尾的位置,也是文件大小
cout <<
pos <<
endl;
fin.
close();
return 0;
}
C 库
fseek ftell
Linux 系统调用
lseek lseek(fd,0,SEEK_CUR);
***************************************************************************************
62--istringstream ostringstream
#include
<iostream>
#include
<sstream>
#include
<string>
using
namespace
std;
int
main(
void)
{
string
line;
string
word;
while (
getline(
cin,
line))
{
istringstream
iss(
line);
while (
iss>>
word)
{
cout <<
word <<
"#";
}
cout <<
endl;
}
return 0;
}
***************************************************************************************
#include
<iostream>
#include
<sstream>
#include
<string>
using
namespace
std;
string
doubletostr (
double
val )
{
ostringstream
oss;
oss <<
val;
return
oss.
str();
}
double
strtodouble(
const
string&
str)
{
istringstream
iss(
str);
double
val;
iss >>
val;
return
val;
}
int
main(
void)
{
string
line;
string
word;
double
val = 55.55;
string
str =
doubletostr(
val);
cout <<
str <<
endl;
str =
"123.123";
val =
strtodouble(
str);
cout <<
val <<
endl;
return 0;
}
***************************************************************************************
63--
流操纵算子/功能描述
setbase(int base) 以进制基数base为输出整数值
setprecision(int n) 将浮点精度设置为n
setw(int n) 按照n个字符来读或者写
flush 刷新ostream缓冲区
ends 插入字符串结束符,然后刷新ostream缓冲区
endl 插入换行符,然后刷新ostream缓冲区
ws 跳过空白字符
setfill(int ch) 用ch填充空白字符
dec 十进制
oct 八进制
hex 十六进制
setiosflags(long lflags) 根据ios类中的枚举设置特定的格式
***************************************************************************************
#include
<iostream>
#include
<sstream>
#include
<string>
#include
<iomanip>
using
namespace
std;
//宽度控制
//对齐控制
//填充控制
//精度控制
//进制输出
int
main(
void)
{
//system("chcp 936");//如果控制台不能输出中文,将活动代码页设置为936
int
n = 64;
double
d = 123.45;
double
d2 = 0.0187;
cout <<
"=================宽度控制=======================" <<
endl;
cout <<
n <<
'#' <<
endl;
cout <<
setw(10) <<
n <<
'#' <<
n <<
endl;
//宽度控制不会影响下一个输出
cout <<
"=================对齐控制=======================" <<
endl;
cout <<
setw(10) <<
setiosflags(
ios::
left) <<
n <<
'#' <<
endl;
cout <<
setw(10) <<
n <<
'#' <<
endl;
//对齐控制会影响下一个输出
//cout << setw(10) << setiosflags(ios::right) << n << '#' << endl;
cout <<
setw(10) <<
resetiosflags(
ios::
left) <<
n <<
'#' <<
endl;
cout <<
"=================填充控制=======================" <<
endl;
cout <<
setw(10) <<
setfill(
'?') <<
n <<
'#' <<
endl;
cout <<
setw(10) <<
n <<
'#' <<
endl;
//填充控制会影响下一个输出
cout <<
setw(10) <<
setfill(
' ') <<
n <<
'#' <<
endl;
cout <<
"=================精度控制=======================" <<
endl;
cout <<
setprecision(4) <<
d <<
endl;
//设置有效数字位数
cout <<
setprecision(2) <<
d2 <<
endl;
cout <<
setiosflags(
ios::
fixed);
//设置小数点位数
cout <<
setprecision(4) <<
d <<
endl;
cout <<
setprecision(2) <<
d2 <<
endl;
cout <<
"=================进制输出=======================" <<
endl;
cout <<
n <<
endl;
/*cout << resetiosflags(ios::dec);
cout << setiosflags(ios::oct) << n << endl;
cout << resetiosflags(ios::oct);
cout << setiosflags(ios::hex) << n << endl;*/
cout <<
oct <<
n <<
endl;
cout <<
hex <<
n <<
endl;
cout <<
setiosflags(
ios::
showbase);
cout <<
dec <<
n <<
endl;
cout <<
oct <<
n <<
endl;
cout <<
hex <<
n <<
endl;
cout <<
endl;
cout <<
setbase(10) <<
n <<
endl;
cout <<
setbase(8) <<
n <<
endl;
cout <<
setbase(16) <<
n <<
endl;
return 0;
}
***************************************************************************************
#include
<iostream>
#include
<string>
#include
<iomanip>
//#include <iomanip>
using
namespace
std;
//宽度控制
//对齐控制
//填充控制
//精度控制
//进制输出
int
main(
void)
{
//system("chcp 936");//如果控制台不能输出中文,将活动代码页设置为936
int
n = 64;
double
d = 123.45;
double
d2 = 0.0187;
cout <<
"=================宽度控制=======================" <<
endl;
cout <<
n <<
'#' <<
endl;
cout.
width(10);
cout <<
n <<
'#' <<
n <<
endl;
//宽度控制不会影响下一个输出
cout <<
"=================对齐控制=======================" <<
endl;
cout.
width(10);
cout.
setf(
ios::
left);
cout <<
n <<
'#' <<
endl;
cout <<
setw(10) <<
n <<
'#' <<
endl;
//对齐控制会影响下一个输出
/*cout.width(10);
cout.setf(ios::right);*/
cout.
width(10);
cout.
unsetf(
ios::
left);
cout <<
setw(10) <<
n <<
'#' <<
endl;
cout <<
"=================填充控制=======================" <<
endl;
cout.
width(10);
cout.
fill(
'?');
cout <<
n <<
'#' <<
endl;
cout.
width(10);
cout <<
n <<
'#' <<
endl;
//填充控制会影响下一个输出
cout.
width(10);
cout.
fill(
' ');
cout <<
n <<
'#' <<
endl;
cout <<
"=================精度控制=======================" <<
endl;
cout.
precision(4);
cout <<
d <<
endl;
//设置有效数字位数
cout.
precision(2);
cout <<
d2 <<
endl;
cout.
setf(
ios::
fixed);
//设置小数点位数
cout.
precision(4);
cout <<
d <<
endl;
cout.
precision(2);
cout <<
d2 <<
endl;
cout <<
"=================进制输出=======================" <<
endl;
cout.
setf(
ios::
showbase);
cout <<
n <<
endl;
cout.
unsetf(
ios::
dec);
cout.
setf(
ios::
oct);
cout <<
n <<
endl;
cout.
unsetf(
ios::
showbase);
cout <<
n <<
endl;
return 0;
}
***************************************************************************************
ios类中的枚举常量
枚举常量 | 用途 | 枚举常量 | 用途 |
skipws | 跳过空白符 | showbase | 显示基指示符 |
left | 左对齐 | showpoint | 输出小数位数0 |
right | 右对齐 | uppercase | 十六进制大写 |
internal | 符号左对齐,数值右对齐 | showpos | 输出正数符号 |
dec | 十进制 | scientific | 科学计数法 |
oct | 八进制 | fixed | 小数按定点表示 |
hex | 十六进制 |
|
|
ios类提供成员函数对流的状态进行检查和进行输入输出格式控制等操作
函数原型/功能描述
int bad( ) 操作出错是返回非0值
int eof( ) 读取到流中最后的文件结束符时返回非0值
int fail( ) 操作失败是返回非0值
void clear( ) 清楚bad,eof和 fail所对应的标志状态,使之恢复为正常状态
char fill( ) 返回当前使用的填充字符
char fill(char c) 设置流中用于输出数据的填充字符为c的值,返回此前的填充字符
long flags( ) 返回当前用于I/O控制的格式状态字
long flags(long f) 设置格式状态字为f的值,返回此前的格式状态字
int good( ) 操作正常时返回非0值,当操作出错、失败和读到文件结束符时均为不正常,则返回0
int precision( ) 返回输出的有效数字的位数
int precision(int n) 设置浮点数的输出精度n,返回此前的输出精度
int rdstate( ) 正常时返回0,否则返回非0值,与good()相反
long setf(long f) 设置相应的格式化标志,返回此前的设置,多个枚举常量可用按位或操作符连接
long unsetf(long f) 根据参数f清楚相应的格式化标志返回此前的设置
int width( ) 返回当前的输出域宽
int width(int w) 设置下一个数据值的输出域宽为w,返回上一个数据值所规定的域宽
***************************************************************************************
69--模板
#include
<iostream>
using
namespace std;
template <
typename
T>
const
T & max(
const
T&
a,
const
T&
b)
{
return
a <
b ?
b :
a;
}
int main(
void )
{
cout
<< ::max(5.5, 6.6)
<< endl;
return 0;
}
---------------------------------------------------------------------------------------
template <>
//函数模板特化
const
char*
const&
max(
const
char*
const&
a,
const
char*
const&
b)
{
return
strcmp(
a,
b)<0?
a:
b;
}
***************************************************************************************
71--类模板
#ifndef _STACK_H_
#define
_STACK_H_
template <
typename
T>
class
Stack
{
public:
explicit Stack(
int maxSize);
~Stack();
void Push(
const
T& elem);
void Pop();
T& Top();
const
T & Top()
const;
bool Empty()
const ;
private:
T* elems_;
int maxSize_;
int top_;
};
template <
typename
T>
Stack<
T >::Stack(
int
maxSize) :maxSize_(
maxSize), top_(-1)
{
elems_ =
new
T [maxSize_];
}
template <
typename
T>
Stack<
T >::~Stack()
{
delete[] elems_;
}
template<
typename
T>
void
Stack <
T>::Push(
const
T &
elem)
{
if ((top_ + 1) > maxSize_)
throw
out_of_range (
"Stack<>::Push() stack full");
elems_[++top_] =
elem;
}
template<
typename
T>
void
Stack <
T>::Pop()
{
if (top_ + 1 == 0)
throw
out_of_range (
"Stack<>::Push() stack empty");
--top_;
}
template<
typename
T>
T &
Stack <
T>::Top()
{
if (top_ + 1 == 0)
throw
out_of_range (
"Stack<>::Push() stack empty");
return elems_[top_];
}
template<
typename
T>
const
T &
Stack<
T>::Top()
const
{
if (top_ + 1 == 0)
throw
out_of_range (
"Stack<>::Push() stack empty");
return elems_[top_];
}
template<
typename
T>
bool
Stack <
T>::Empty()
const
{
return top_ + 1 == 0;
}
#endif
-----------------------------------------------------------------------------
#include
"Stack.h"
#include
<iostream>
using
namespace std;
int main(
void )
{
Stack<
int > s(10);
s.Push(1);
s.Push(2);
s.Push(3);
while (!s.Empty())
{
cout
<< s.Top()
<< endl;
s.Pop();
}
}
-----------------------------------------------------------------------------
非类型模板参数
template <
typename
T,
int MAX_SIZE>
class
Stack
{
}
***************************************************************************************
71--
#ifndef _STACK_H_
#define
_STACK_H_
#include
<exception>
#include
<deque>
using
namespace std;
template <
typename
T,
typename
CONT =
deque <
T> >
class
Stack
{
public:
Stack() : c_()
{
}
~Stack()
{
}
void Push(
const
T&
elem)
{
c_.push_back(
elem);
}
void Pop()
{
c_.pop_back();
}
T& Top()
{
return c_.back();
}
const
T & Top()
const
{
return c_.back();
}
bool Empty()
const
{
return c_.back();
}
private:
CONT c_;
int top_;
};
#endif
----------------------------------------------------------------------------
#include
"Stack.h"
#include
<iostream>
#include
<vector>
using
namespace std;
int main(
void )
{
//Stack<int> s;
Stack<
int ,
vector<
int> > s;
s.Push(1);
s.Push(2);
s.Push(3);
while (!s.Empty())
{
cout
<< s.Top()
<< endl;
s.Pop();
}
}
----------------------------------------------------------------------------
成员模板
#include
<iostream>
using
namespace std;
template <
typename
T>
class
MyClass
{
private:
T value;
public:
template <
class
X>
void Assign(
const
MyClass<
X>&
x )
{
value =
x.GetValue();
//x.value;无法访问private成员
}
T GetValue()
const
{
return value;
}
};
int main(
void )
{
MyClass<
double > d;
MyClass<
int > i;
d.Assign(d);
//OK
d.Assign(i);
//
OK
return 0;
}
-------------------------------------------------------------------------------
typename
#include
<iostream>
using
namespace std;
template <
typename
T>
class
MyClass
{
private:
typename
T ::
SubType* ptr_;
//表示这是一个类型(如int)而不是引用
};
class
Test
{
public:
typedef
int
SubType;
};
int main(
void )
{
MyClass<
Test > mc;
return 0;
}
***************************************************************************************
72--单例模式 模板实现
Singleton.h
#include
<cstdlib>
#include
<iostream>
using
namespace std;
template <
typename
T>
class
Singleton
{
public:
static
T & GetInstance()
{
Init();
return *instance_;
}
private:
static
void Init()
{
if (instance_ == 0)
{
instance_ =
new
T ;
atexit(Destroy);
}
}
static
void Destroy()
{
delete instance_;
}
Singleton(
const
Singleton & other);
Singleton&
operator= (
const
Singleton& other);
Singleton();
~Singleton();
static
T * instance_;
};
template <
typename
T>
T*
Singleton <
T>::instance_ = 0;
-------------------------------------------
01cpp.cpp
#include
<iostream>
#include
"Singleton.h"
using
namespace std;
class
ApplicationImpl
{
public:
ApplicationImpl() { cout
<<
"ApplicationImpl..."
<< endl; }
~ApplicationImpl() { cout
<<
"~ApplicationImpl..."
<< endl; }
void Run() { cout
<<
"Run..."
<< endl; }
};
typedef
Singleton <
ApplicationImpl>
Application;
int main(
void )
{
Application::GetInstance().Run();
Application::GetInstance().Run();
return 0;
}
***************************************************************************************
73--STL
STL六大组件
Container(容器)各种基本数据结构
Adapter(适配器)可改变containers、iterators或Function object 接口的一种组件
Algorithm(算法)各种基本算法如sort、search...等
Iterator(迭代器)连接containers和algorithms
Function object(函数对象)
Allocate(分配器)
七种基本容器
向量(vector) 双端队列(deque) 列表(list)集合(set)
多重集合(multiset) 映射(map) 多重映射(multimap)
***************************************************************************************
76--
77--
容器成员
value_type | 元素类型 |
allocator_type | 内存管理器类型 |
size_type | 下标,元素计数类型 |
difference_type | 循环子之间差的类型 |
iterator | 循环子,相当于value_type* |
const_iterator | 常循环子,相当于const value_type* |
reverse_iterator | 逆序循环子,相当于value_type* |
const_reverse_iterator | 常逆序循环子,相当于const value_type* |
reference | 元素引用,相当于value_type& |
const_reference | 元素常引用,相当于const value_type& |
key_type | 关键字类型(只用于关联包容器) |
mapped_type | 映射值类型(只用于关联包容器) |
key_compare | 比较标准类型(只用于关联包容器) |
容器成员2
循环子操作 | |
begin( ) | 指向第一个元素 |
end( ) | 指向最后一个元素的最后一个位置 |
rbegin( ) | 指向逆序的第一个元素 |
rend( ) | 指向逆序的最后一个元素的最后一个位置 |
访问元素操作 | |
front( ) | 访问第一个元素 |
back( ) | 访问最后一个元素 |
[ ] | 无测试的下标访问(不用于list) |
at( ) | 有测试的下标访问(只用于vector和deque) |
容器成员3
堆栈和队列操作 | |
push_back( ) | 将新元素加入到尾部 |
pop_back( ) | 移出最后一个元素 |
push_front( ) | 将新元素加入头部(只用于list 和deque) |
pop_front( ) | 移出第一个元素(只用于list 和deque) |
表操作 | |
insert(p,x) | 将元素x加入到p之前 |
insert(p,n,x) | 在p之前加入n个x的拷贝 |
insert(p,first,last) | 在p之前加入区间[first:last)中的序列 |
erase(p) | 删除p处的元素 |
erase(fist,last) | 删除区间[first:last}中的序列 |
clear( ) | 清除所有的元素 |
容器成员4
其他操作 | |
size( ) | 获取元素个数 |
empty( ) | 测试包容器是否为空 |
max_size( ) | 最大可能的包容器的大小 |
capacity( ) | 为向量包容器分配的空间(只用于vector) |
reserve( ) | 为扩充向量包容器保留空间(只用于vector) |
resize( ) | 改变包容器的大小(只用于vecotr,list和deque) |
swap( ) | 交换两个包容器中的元素 |
get_allocator( ) | 获取包容器的内存管理器的副本 |
== | 测试两个包容器的内容是否相等 |
!= | 测试两个包容器的内容是否不等 |
< | 测试一个包容器是否在另一个包容器字典序之前 |
容器成员5
构造函数、析构函数 | |
container( ) | 构造一个空包容器 |
container( n) | 用缺省值构造n个元素的包容器(不能用于关联包容器) |
container(n,x) | 构造具有n个x拷贝的包容器(不能用于关联包容器) |
container(first,last) | 初始化区间[first,last)上的元素 |
container(x) | 拷贝构造函数 |
~container( ) | 析构包容器和它的全部元素 |
容器成员6
分配操作 | |
operator=(x) | 从包容器x中元素拷贝分配 |
assign(n,x) | 分配n个x的拷贝(不能用于关联包容器) |
assign(first,last) | 从区间[first,last)中分配 |
关联操作 | |
operator[ ](k) | 访问带有关键字k的元素(用于具有唯一关键字的包容器) |
find(k) | 查找带有关键字k的元素 |
lower_bound(k) | 查找带有关键字k的第一个元素 |
upper_bound(k) | 查找带有大于k关键字的第一个元素 |
equal_range(k) | 查找带有关键字k的元素的lower_bound和upper_bound |
key_comp( ) | 获取关键字比较对象的拷贝 |
value_comp( ) | 获取映射值比较对象的拷贝 |
78--
算法分类
#include
<algorithm>
非变动性算法
变动性算法
移出性算法
变序性算法
排序算法
已序区间算法
用来处理数值的算法 需要加上头文件#include<numberic>
非变动性算法 | |
for_each( ) | 对每个元素执行某个操作 |
count( ) | 返回元素个数 |
count( )_if( ) | 返回某一条件的元素个数 |
min_element( ) | 返回最小值元素 |
max_element() | 返回最大值元素 |
find( ) | 搜索等于某个值的第一个元素 |
find_if( ) | 搜索满足某个条件的第一个元素 |
search_n( ) | 搜索具有某特性的第一段n个连续元素 |
search( ) | 搜索某个子区间第一次出现位置 |
find_end( ) | 搜索某个子区间最后一次出现位置 |
find_first_of( ) | 搜索等于“某数个值之一”的第一元素 |
adjacent_find( ) | 搜索连续两个相等的元素 |
equal( ) | 判断两区间是否相等 |
mismatch( ) | 返回两个序列的各组对应元素中,第一对不相等元素 |
lexicographical_compare( ) | 用于按字典序比较两个序列 |
变动性算法 | |
for_each( ) | 对每个元素执行某操作 |
copy( ) | 从第一个元素开始,复制某段区间 |
copy_backward( ) | 从最后一个元素开始,复制某段区间 |
transform( ) | 变动(并复制)元素,将两个区间的元素合并 |
merge( ) | 合并两个区间 |
swap_ranges( ) | 交换两区间内的元素 |
fill( ) | 以给定值替换每一个元素 |
fill_n( ) | 以给定值替换n个元素 |
generate( ) | 以某项操作的结果替换每一个元素 |
gennerate_n( ) | 以某项操作的结果替换n元素 |
replace( ) | 将具有某特定值的元素替换为另一个值 |
replace( )_if( ) | 将符合某准则的元素替换为另一值 |
replace( )_copy( ) | 复制某个区间,同时并将具有某特定值的元素替换为另一个元素 |
replace( )_copy_it( ) | 复制某个区间,同时并将符合某个条件的元素替换为另一个元素 |
变序性算法 | |
reverse( ) | 将元素的次序逆转 |
reverse_copy( ) | 复制的同时,逆转元素顺序 |
rotate( ) | 旋转元素次序 |
rotate_copy( ) | 复制的同时,旋转元素顺序 |
next_permutation( ) | 得到元素的下一个排序次序 |
prev_permutation( ) | 得到元素的上一个排序顺序 |
random_shuffle( ) | 将元素的次序随机打乱 |
partition( ) | 改变元素次序,是符合走准则值移到前面 |
stable_partition( ) | 与partition( )相似,但保持符合准则与不符合准则各个元素之间的相对位置 |
排序算法 | |
sort( ) | 对所以元素排序 |
stable_sort( ) | 对所以元素排序,并保持相等元素间的相对次序 |
partial_sort( ) | 排序,直到前n个元素就位 |
partial_sort_copy( ) | 排序,直到前n个元素就位,结果复制于它处 |
nth_element( ) | 根据第n个位置进行排序 |
partition( ) | 改变元素次序,使符合某准则的元素在前面 |
stable_partition( ) | 与partiton( )相同,但保持相对位置 |
make_heap( ) | 将一个区间转换成一leap |
push_heap( ) | 将元素加入一个heap |
pop_heap( ) | 从heap移除一个元素 |
sort_heap( ) | 对heap进行排序,排序后就不再是heap了 |
已序区间算法 | |
binary_search( ) | 判断某区间内是否包含某个元素 |
includes( ) | 判断某区间内的每一个元素是否都涵盖与另一区间中 |
lower_bound( ) | 搜索第一个“大于等于给定值”的元素 |
upper_bound( ) | 搜索第一个“大于给定值”的元素 |
equal_range( ) | 返回“等于给定值”的所有元素构成的区间 |
merge( ) | 将两个区间合并 |
set_union( ) | 求两个区间的并集 |
set_intersection( ) | 求两个区间的交集 |
set_difference( ) | 求位于第一区间但不位于第二区间的所有元素,形成一个已序区间 |
set_symmetric_difference( ) | 找出只出现于两区间之一的所有元素,形成一个已序区间 |
inplace_merge( ) | 将两个连续的已序区间合并 |
数值算法 | |
accumulate ( ) | 组合所有元素(求总和,求乘积。。。) |
inner_product( ) | 组合两区间内的所有元素 |
adjacent_difference( ) | 将每个元素和其前一个元素组合 |
partial_sum( ) | 将每个元素和其先前的所有元素组合 |
82--
STL中内置的函数对象
断言函数对象
equal_to arg1==arg2
not_equal_to arg1!=arg2
greater arg1>arg2
less arg1<arg2
greater_equal arg1>=arg2
less_equal arg1<=arg2
logic_and arg1&&arg2
logic_or arg1||arg2
logic_not !arg
算术操作函数对象
plus arg1+arg2
minus arg1-arg2
multiplies arg1*arg2
divides arg1/arg2
modulus arg1%arg2
negate -arg
***************************************************************************************
82--函数对象
#include
<iostream>
#include
<string>
#include
<vector>
#include
<algorithm>
using
namespace std;
void print_element(
int
n)
{
cout
<<
n
<<
' ';
}
class
PrintObj
{
public:
void
operator() (
int
n)
{
cout
<<
n
<<
" ";
}
};
class
AddObj
{
public:
AddObj(
int
number ) :number_(
number)
{
}
void
operator() (
int&
n)
{
n += number_;
}
private:
int number_;
};
class
GreaterObj
{
public:
GreaterObj(
int
number ) :number_(
number)
{
}
bool
operator() (
int
n)
{
return
n > number_;
}
private:
int number_;
};
int main(
void )
{
int a[] = { 1,2,3,4,5 };
vector<
int > v(a, a + 5);
for_each(v.begin(), v.end(),
PrintObj( ));
cout
<< endl;
for_each(v.begin(), v.end(),
AddObj(5));
for_each(v.begin(), v.end(),
PrintObj( ));
cout
<< endl;
cout
<< count_if(a, a + 5,
GreaterObj (3))
<< endl;;
return 0;
}
83--
三种类型的适配器
容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈、队列和优先级队列
迭代器适配器(反向迭代器、插入迭代器、IO流迭代器)
函数适配器
***************************************************************************************
#include
<iostream>
#include
<functional>
#include
<vector>
#include
<algorithm>
using
namespace std;
bool is_odd(
int
n)
{
return
n % 2;
}
int main(
void )
{
int a[] = { 1,2,3,4,5 };
vector<
int > v(a, a + 5);
cout
<< count_if(v.begin(), v.end(), is_odd)
<< endl;
cout
<< count_if(v.begin(), v.end(), bind2nd(
modulus<
int>(), 2))
<< endl;
cout
<< count_if(v.begin(), v.end(), bind1st(
less<
int>(), 2))
<< endl;
return 0;
}
***************************************************************************************
#include
<iostream>
#include
<functional>
#include
<vector>
#include
<algorithm>
#include
<string>
using
namespace std;
class
Person
{
public:
Person(
const
string &
name) :name_(
name) {}
void Print()
const { cout
<< name_
<< endl; }
void PrintWithPrefix(
string
prefix)
const { cout
<<
prefix
<< name_
<< endl; }
private:
string name_;
};
void foo(
const
vector<
Person>&
v )
{
for_each(
v.begin(),
v .end(), mem_fun_ref(&
Person::Print));
for_each(
v.begin(),
v .end(), bind2nd(mem_fun_ref(&
Person::PrintWithPrefix),
"Person:"));
}
void foo2(
const
vector<
Person*>&
v )
{
for_each(
v.begin(),
v .end(), mem_fun(&
Person::Print));
for_each(
v.begin(),
v .end(), bind2nd(mem_fun(&
Person::PrintWithPrefix),
"Person:"));
}
int main(
void )
{
vector<
Person > v;
v.push_back(
Person(
"tom" ));
v.push_back(
Person(
"jerry" ));
foo(v);
vector<
Person *> v2;
v2.push_back(
new
Person (
"tom"));
v2.push_back(
new
Person (
"jerry"));
foo2(v2);
return 0;
}
***************************************************************************************
84--stl
插入迭代器
back_insert_iterator
back_inserter
font_insert_iterator
font_inserter
***************************************************************************************
#include
<iostream>
#include
<vector>
#include
<string>
#include
<iterator>
using
namespace std;
void ShowVec(
const
vector<
int>&
v )
{
for (
vector <
int>::
const_iterator it =
v .begin();it
!=
v.end();
++it)
{
cout
<<
* it
<<
' ' ;
}
cout
<< endl;
}
int main(
void )
{
int a[] = { 1,2,3,4,5 };
vector<
int > v(a, a + 5);
vector<
int > v2;
back_insert_iterator<
vector <
int> >bii(v);
*bii
= 6;
ShowVec(v);
back_insert_iterator<
vector <
int>> bii2(v2);
copy(v.begin(), v.end(), bii2);
ShowVec(v2);
return 0;
}
------------------------------------------------------------------------
#include
<iostream>
#include
<vector>
#include
<string>
#include
<iterator>
using
namespace std;
int main(
void )
{
int a[] = { 1,2,3,4,5 };
vector<
int > v(a, a + 5);
copy(v.begin(), v.end(),
ostream_iterator<
int >(cout,
" "));
return 0;
}
----------------------------------------------------------------------------------
#include
<iostream>
#include
<vector>
#include
<string>
#include
<iterator>
using
namespace std;
int main(
void )
{
vector<
int > v;
copy(
istream_iterator<
int >(cin),
istream_iterator<
int>(), back_inserter(v));
//ctrl+z结束,linux下ctrl+d结束
copy(v.begin(), v.end(),
ostream_iterator<
int >(cout,
" "));
return 0;
}
***************************************************************************************
85--容器适配器
stack
queue
priority_queue
***************************************************************************************
87--boost智能指针
智能指针是利用RALL(Resource Acquisition Is Inithialization;资源获取即初始化)来管理资源
scoped_ptr<T> | 当这个指针的作用域结束之后自动释放,与auto_ptr不同之处在于,所有权不能转移,但是可以交换 |
shared_ptr<T> | 内部维护一个引用计数器来判断此指针是不是需要被释放。线程安全 |
intrusive_ptr<T> | 也维护一个轻量级的引用计数器,比shared_ptr有更好的性能,但是要求T自己提供这个计数器 |
weak_ptr<T> | 弱指针,它不能控制对象的生命周期,但是它知道对象是否还活着,如果对象还活着,那么它可以提升(promote)为有效的shared_ptr;如果对象已经死了,提升会失败,返回一个空的shared_ptr。 |
scoped_array<T> | 与scoped_ptr相似,用来处理数组。 |
shared_array<T> | 与shared _ptr相似,用来处理数组。 |
***************************************************************************************
#include
<boost/scoped_ptr.hpp>
#include
<iostream>
using
namespace std;
class
X
{
public:
X() { cout
<<
"X...."
<< endl; }
~X() { cout
<<
"~X...."
<< endl; }
};
int main(
void )
{
cout
<<
"Entering main...."
<< endl;
{
boost::scoped_ptr<X> p(
new
X );
}
cout
<<
"Exiting main..."
<< endl;
}
***************************************************************************************
auto_ptr<T>不能放置vector中
但shared_ptr<T>可以放置vector中
#include
<boost\shared_ptr.hpp>
#include
<iostream>
#include
<memory>
#include
<vector>
using
namespace std;
class
X
{
public:
X() { cout
<<
"X...."
<< endl; }
~X() { cout
<<
"~X...."
<< endl; }
};
int main(
void )
{
/*错误
vector<auto_ptr<X>> v;
auto_ptr<X> p(new X);
v.push_back(p);
*/
vector<boost::
shared_ptr <
X>> v;
boost::
shared_ptr<
X > p(
new
X);
v.push_back(p);
return 0;
}
***************************************************************************************
#include
<boost\shared_ptr.hpp>
#include
<boost\weak_ptr.hpp>
#include
<iostream>
#include
<memory>
#include
<vector>
using
namespace std;
class
X
{
public:
X() { cout
<<
"X...."
<< endl; }
~X() { cout
<<
"~X...."
<< endl; }
void Fun() { cout
<<
"fun..."
<< endl; }
};
int main(
void )
{
boost::
weak_ptr<
X > p;
{
boost::
shared_ptr<
X > p2(
new
X);
cout
<< p2.use_count()
<< endl;
p
= p2;
cout
<< p2.use_count()
<< endl;
boost::
shared_ptr<
X > p3 = p.lock();
if (
! p3)
cout
<<
"object is destroyed"
<< endl;
else
{
p3
->Fun();
}
}
boost::
shared_ptr<
X > p4 = p.lock();
if (
! p4)
cout
<<
"object is destroyed"
<< endl;
else
p4
->Fun();
return 0;
}
***************************************************************************************