同种数据类型、最长的数据类型、pragma pack(n)
2.优先队列:
取出优先级最小或最大的元素,进行删除和读取 堆作为存储结构,时间可提高到O(log2n)
双端队列:在两端都可删除和插入,而不是队列只能在尾插入,在头删除
3.智能指针:
原理:引用计数,每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,析构函数减少引用计数(如果引用计数减至0,则删除基础对象)
两个对象,其中一个临时:类TestPtr对象的任何拷贝、赋值操作都会使多个TestPtr对象共享相同的指针。但在一个对象发生析构时,指针指向的对象将被释放,从而可能引起悬垂指针。
删除指针后即引用计数为零后才删除对象:其实,智能指针的引用计数类似于java的垃圾回收机制:java的垃圾的判定很简答,如果一个对象没有引用所指,那么该对象为垃圾。系统就可以回收了。
4.long atoi(const char* str)
char * itoa(int i,char *str,int jinzhi) _itoa_s(int i,char *str,int len,int jinzhi)
5.各个文件中定义的全局变量名不可相同
在不同的C文件中以static形式来声明同名全局变量。可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错
把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。static函数与普通函数作用域不同。仅在本文件。
A.cpp
extern int i;
int main()
{
i = 56;
}
B.cpp
int i;
6.字符串反转:两个变量
把字符串“I am a student”反转成为“student a am I” :以' '为出发点,双重循环即可
实现一个string
7.洗牌算法
这个算法的要求是这样的:将N个数乱序后输出.由于和扑克牌的洗牌过程比较相似所以我也就称为洗牌算法了.很多地方都不自觉的需要这个算法的支持.也可以将这个算法扩展为从N个数中取出M个不重复的数(0<M<=N).
算法(Java):
public HashSet getRamdomNumber(int total,int number){
//在0到total-1中随机生成number个不重复的随机数
}
算法:
void shuffle ( int a[], int n )
{
}
算法:
void shuffle()
{
}
/*n个字符的数组,只有一个元素出现的次数最多,找出该元素*/
char FindIt(char a[],int n)
{
char ch;
int times=0;
int i;
for(i=0;i<n;i++)
{
if(times==0)/*计数清零,从本次开始选取新的字符*/
{
ch=a[i];
times=1;
}
else if(ch==a[i])/*找到相同的计数加1*/
times++;
else/*与备选的字符ch不同,计数-1.做一次抵消。只有次数最多的才会保留到最后*/
times--;
}
return ch;
}
9.寻找最大的K个数:哈希后排序(如果有重复的数据)
10.判断一个单链表是否存在循环
p=head
q=head
while(p && q && q->next)
{
p=p->next; q=q->next->next
if (p==q)
return true
}
return 0;
11.x==(y=z) cout<<x<<endl; x并未改变
printf从右到左压栈
float a = 1.0f;
cout<<(int &)a<<endl;输出的不是1,因为整数和浮点数的存储方式不一样,这里相当于把浮点数的前sizeof(int)输出
!(x&(x-1))判断x是否是2的n次方
a、b中数据较大的:(a+b + abs(a-b))/2 不用if
a、b交换不用中间变量:a=a+b;b=a-b;a=a-b; a=a^b;b=a^b;a=a^b;
#ifndef、#define、#endif:防止头文件被重复引用
const和#define:类型安全、对const调试
修饰为const的成员函数:修改成员变量可用mutable修饰
string有28字节
一个空类占1字节,虚基类占4字节
const常量必须初始化
void GetMemory(char **p,int num)
{
*p = (char *)malloc(sizeof(char)*num);
}//char *str = NULL;GetMemory(&str,100);strcpy(str,"hello"); 字符串很特殊,不像int
char *GetMemory(char *p,int num)
{
p = (char *)malloc(sizeof(char)*num);这里的p是分配的全局数组,存储在静态存储区
return p;
}//char *str = NULL;str=GetMemory(str,100);strcpy(str,"hello");
指向常量的指针:int *const i;
int (*(*f)(int,int))(int):f是函数指针,其返回值也是个函数指针
vector:push_back、pop_back(可能会调用拷贝构造函数)、vector<int>::iterator、ver.begin()、ver.size()
struct和class唯一的不同是默认的访问控制是public
初始列表的初始化是根据 成员变量的声明顺序来执行的
每个虚函数的对象都需维护一个v表
单个参数的构造函数如果不添加explicit关键字,会定义一个隐含的类型转换如int到class
assert false:assert是Debug版本的宏、断言
12.字符串:
整数转字符串
int num = 4678788;
while (num)
{
ch[i] = num % 10 + '0';
i++;
num = num / 10;
}
字符串转整数
char *ch = {"64388"};
while (ch[i]!='\0')
{
num = num*10 + ch[i]-'0';
i++;
}
字符串拷贝:
char *strcpyfun(char *des, const char*sour)
{
assert((des != NULL) && (sour != NULL));
char *ret;
while ((*des++=*sour++)!='\0');
ret = des;
return ret;
}
13. 代码规范:空格、int *t、注释/****/、命名(前缀、名词、m_ s_ g_)
14.迭代器失效:重新分配内存 map实现:红黑树实现的,红黑树是一种自平衡二叉查找树。
序列性容器::(vector)
iter = c.erase(iter);
for( iter = c.begin(); iter != c.end(); )
c.erase(iter++);
其实对于list两种方式都可以正常工作
15.内存初始化、越界、释放(delete后指针要设为NULL,杜绝野指针)
char *pChar = "hello";
char *pValue = new char[strlen(pChar)+1];
strcpy_s(pValue,6,pChar);
pValue[0] = 'H';
printf("%s\n",pValue);
释放了内存,释放了指针
void Func(void) //处理内存耗尽,找不到多余的内存,返回NULL
{
A *a = new A;
if(a == NULL)
{
cout << “Memory Exhausted” << endl;
exit(1); //出错处理程序
}
⋯
}
16.
(1)函数 Derived::f(float)覆盖了 Base::f(float)。
(2)函数 Derived::g(int)隐藏了 Base::g(float),而不是重载。
(3)函数 Derived::h(float)隐藏了 Base::h(float),而不是覆盖。
c语言不支持函数重载
17. C++ 程序中,应该用内联函数取代所有宏代码,“断言 assert” 恐怕是唯一的例外
内联:宏、函数定义时inline、类
18.delete后要设为NULL
class String
{
public:
String(const char *ch = NULL);
String(const String &sValue);
String &operator =(const String &sValue);
~String(void);
private:
char *m_chValue;
};
String::String(const char *ch)
{
if (ch == NULL)
{
m_chValue = new char[1];
*m_chValue = '\0';
}
else
{
int strlength = strlen(ch);
m_chValue = new char[strlength + 1];
strcpy(m_chValue, ch);
}
}
String::String(const String &sValue)
{
int strlength = strlen(sValue.m_chValue);
m_chValue = new char[strlength + 1];
strcpy(m_chValue, sValue.m_chValue);
}
String &String::operator =(const String &sValue)
{
if (this == &sValue)
return *this;
delete[] m_chValue;
int strlength = strlen(sValue.m_chValue);
m_chValue = new char[strlength + 1];
strcpy(m_chValue, sValue.m_chValue);
return *this;
}
String::~String()
{
delete[] m_chValue;
}
19.
对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”, 目的是提高效率。例如将 void Func(A a) 改为 void Func(const A &a)。
对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否 则既达不到提高效率的目的,又降低了函数的可理解性。例如 void Func(int x) 不应 该改为 void Func(const int &x)。