0%

stack的基本使用

1
2
3
4
5
6
7
8
9
10
11
#include<stack>
stack<int> st;
st.push(1);
st.push(2);
st.push(3);
while(!st.empty())
{
cout << st.top() << " ";
st.pop();
}
cout << endl;
阅读全文 »

list的基本使用

本质为双向带头循环列表

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向带头循环链表,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
  3. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
  4. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)
阅读全文 »

vector的基本使用

1
2
3
4
5
6
7
8
9
10
vector<int> v;
vector<char> v2;
vector<string> v3;

vector<int> v4(10, 5);//10个5

string s2 = "0123456789";
vector<char> v5(s2.begin(), s2.end());

vector<char> v6(v5);
阅读全文 »

string类基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>

void test()
{
string str;//""
string str2("123");//"123"
string str3 = "abc";//"abc"
string str4("0123456789", 5);//"01234"
string cpy(str3);//"abc"

string str5(str4, 2, 2);//"23" 从str4的第2个位置拿两个字符创建一个字符串
string str6(10, a);//"aaaaaaaaaa"

str6 = str5;//操作符重载
str6 = "321";
str6 = "xyz";
}
阅读全文 »

泛型编程

编写与类型无关的代码

1
template <typename / class 泛型参数1, typename / class 泛型参数2 ...... >

告诉编译器一个模板,让编译器根据不同的类型利用该模板生成代码

阅读全文 »

C/C++内存分布

  1. 栈:非静态局部变量,函数参数,返回值等,栈是向下增长的
  2. 内存映射段:装载一个共享的动态内存库
  3. 堆:用于程序运行时动态内存分配,可以向上增长
  4. 数据段:存储全局变量和静态数据
  5. 代码段:可执行的代码、只读常量
阅读全文 »

再谈构造函数

初始化列表::成员(初始化/表达式),成员2()…

每个成员变量只能在初始化列表中出现一次

对象成员必须在定义时初始化的地方:初始化列表

如果有引用成员、const成员、没有默认构造的自定义成员,必须在初始化列表中进行初始化

其他成员可以不进行显示初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Time
{
public:
Time(int a)
{
_a = a;
}
private:
int _a;
};
class Date
{
public:
Date(int y = 1, int m = 1, int d = 1)
:_a(d)
,_b(d)
,_time(10)
{
_year = y;
_month = m;
_day = d;
}
private://成员变量声明的地方,此处不是定义的地方
int _year;
int _month;
int _day;
int& _a;//引用在定义时必须初始化
const int _b;//const变量在定义时必须初始化
Time _time;//没有默认构造的自定义成员在定义时必须初始化
};

对于自定义成员,最好在初始化列表中初始化,即使不在初始化列表中显示初始化,编译器也会在初始化列表中自动调用自定义成员的默认构造完成初始化

成员变量在初始化列表中的初始化顺序:和声明顺序一致,与其在初始化列表中的顺序无关

注意:最好初始化列表中的成员顺序和声明顺序保持一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A
{
public:
// explicit: //可以禁止掉单参构造函数的隐式类型转化
A(int a)
:_a(a)
{}
A(const A& a)
:_a(a._a)
{}
private:
int _a;
};

void test()
{
A a(1);//创建对象
A a2 = 2;//创建对象:单参构造函数的隐式类型转换 ---> 调用构造创建一个匿名对象,+拷贝构造(通过匿名对象拷贝构造a2对象)
//此时用2创建了一个匿名对象,在调用拷贝构造创建a2
a2 = 3;//3作为参数传入构造函数, 创建匿名对象,调用赋值重载函数,使用匿名对象给a2赋值
//只支持单参构造函数的隐式类型转换,下面的代码不支持
//a3 = (1, 2);
}

explicit: 可以禁止掉单参构造函数的隐式类型转化

static 成员

static可以修饰类的成员变量,成为静态成员变量,也可以修饰成员函数,称为静态成员函数

_静态的成员变量,必须要在类外进行初始化_,定义时不加static关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A
{
public:
A()
{_count++;}
A(const A& t)
{_count++;}
static int GetCount()
{return _count;}
private:
static int _count;
};

int A::_count = 0; //静态的成员变量,必须要在类外进行初始化

void test()
{
cout << A::GetCount() << endl;
A a1, a2;
A a3(a1);
cout << A::GetCount() << endl;
}

特点:

  1. 静态成员变量,所有对象共享此成员变量,可以看成类成员,使用时类名::静态成员变量或对象
  2. 静态成员变量不能在声明时给默认值
  3. 静态成员变量不在对象模型中,一般放在数据段,不能再初始化列表中初始化
  4. 静态成员函数没有this指针,不能访问任何非静态成员(因为非静态成员需要this指针)

普通成员只能通过对象访问,不能通过类名访问

友元

友元函数

友元函数:friend + 正常函数的定义 / 声明

友元函数可以访问类的私有成员

友元函数不是类的成员函数,它是普通的非成员函数(没有this指针

只需要在类中声明友元函数,不需要在类中定义

友元函数可以声明在类的任何地方,不受访问限定符的约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class A
{
public:
friend ostream& operator<<(ostream& _cout, A& a);//返回输出流类型是为了支持连续输出
A()
{_count++;}
A(const A& t)
{_count++;}
static int GetCount()
{return _count;}
private:
static int _count;
};

int A::_count = 0; //静态的成员变量,必须要在类外进行初始化
ostream& operator<<(ostream& _cout, A& a)
{_cout << a._count << endl;}

void test()
{
cout << A::GetCount() << endl;
A a1, a2;
A a3(a1);
cout << A::GetCount() << endl;
cout << a1 << a2 << a3;
}

尽量少用,它是一种突破封装的语法

友元类

如果一个类是另外一个类的友元类,则此类中的所有成员函数即为另一个类的友元函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class B
{
public:
//DisPlay, Fun1, Fun2都为A类的友元函数
void DisPlay(const A& a)
{
cout << a._a << endl;
}
void Fun1(const A& a)
{
cout << a._a << endl;
} void Fun2(const A& a)
{
cout << a._a << endl;
}
};

class A
{
public:
friend class B;
private:
int _a;
}

友元关系是单向的!!!,友元关系也不能传递

内部类

在一个类的内部定义一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
{
public:
class B
{
public:
private:
int _b;
class C
{
public:
private:
int _c;
}
}
private:
int _a;
}

内部类天然的作为一其外部类的友元类,即内部类可以访问外部类的成员

可通过外部类对象访问外部类的私有成员

可直接访问外部类的static成员

内部类独立存在,不附属于外部类

外部类不能看作内部类的友元类,对于内部类的成员没有特殊的访问权限,需要遵循访问限定符的限制

总结

静态成员: static +成员变量/函数:
静态成员函数:

  1. 静态成员函数:函数内部没有this指针

  2. 静态成员函数不能访问非静态成员函数变量–>因为非静态成员需要this指针,但是静态成员函数内部缺少this指针,所以不能访问3.非静态成员函数可以访问静态成员函数变量

静态成员变量:

  1. 静态成员变量,所有对象共享此成员变量,可以看成类成员

  2. 静态成员变量不能在声明的时候给默认

  3. 静态成员不在对象模型中,一般存放在数据段, 不能在初始化列表中初始化

  4. 静态成员必须在类外初始化

静态成员变量/静态成员函数访问方式:

  1. 对象访问

  2. 类名+作用域限定符

  3. 普通成员只能通过对象访问,不能通过类名访问

友元函数: friend +函数定义:

  1. 友元函数尽量少用,它是一-种突破封装的语法

  2. 友元函数可以访问类的私有成员

  3. 友元函数不是类的成员函数,它是普通的非成员函数

  4. 只需要在类中声明友元函数,不需要在类中定义

  5. 友元函数可以声明在类的任何地方,不受访问限定符的限制

友元类: friend class 类名:

  1. 友元关系是单向的

  2. 如果一个类是另一个类的友元类,则此类中的所有成员函数即为另一个类的友元函数

  3. 友元关系不能传递,类似于朋友的朋友不一定是自己的朋友

内部类:在一个类内部定义一个新的类

  1. 内部类天然的作为外部类的友元类

  2. 内部类作为一-个独立的类存在,不附属于外部类

  3. 外部类不能看作内部类的友元类,对于内部类的成员没有特殊的访问权限,需要遵循访问限定符的限制

  4. .可以通过外部类对象访问外部类的私有成员

  5. 可以直接访问外部类的static成员

类的 6 个默认成员函数

初始化和清理:

  1. 构造函数主要完成初始化工作
  2. 析构函数主要完成清理工作

拷贝复制:

  1. 拷贝构造是使用同类对象初始化创建对象
  2. 复制重载主要是把一个对象赋值给另一个对象

取地址重载:

主要是普通对象和const对象取地址,这两个很少会自己实现

阅读全文 »

类的定义

C++ struct:可以定义数据以及函数,一般使用class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct Student
{
void display()
{

}
void setId(int id)
{
_id = id
}
char name[10];
int _id;
};

class Student
{//成员函数
public://共有成员在任何地方可用
void display()
{

}
void setId(int id)
{
_id = id
}
private://私有的成员在类外不可见
//成员变量,属性
char name[10];
int _id;
protected://保护的成员在类外不可见
char major[10];
};
阅读全文 »

命名空间

对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的

阅读全文 »