Mrli
别装作很努力,
因为结局不会陪你演戏。
Contacts:
QQ博客园

C++学习笔记

2019/09/15 C++ 计算机基础知识
Word count: 3,127 | Reading time: 12min

C++学习笔记

system()就是调用(DOS)系统命令(和shell命令)。
pause ,即DOS命令集合中的暂停命令;

sprintf

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main( void )
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f; // 格式化并打印各种数据到buffer
j = sprintf( buffer, " String: %s\n", s ); // C4996
j += sprintf( buffer + j," Character: %c\n", c );
j += sprintf( buffer + j," Integer: %d\n", i );
j += sprintf( buffer + j," Real: %f\n", fp );
printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
  • 返回写入buffer 的字符数,出错则返回-1. 如果 buffer 或 format 是空指针,且不出错而继续,函数将返回-1
  • sprintf 返回以format为格式argument为内容组成的结果被写入buffer 的字节数,结束字符‘\0’不计入内。即,如果“Hello”被写入空间足够大的buffer后,函数sprintf 返回5。

引用

声明引用:

1
2
int a = 1;
int &c=a; //int & c=a; △.声明引用时必须初始化

传引用参数

1
2
void func(int& a){} //函数名(xxx)xxx其实是创建形参变量的过程
func(b);

传指针

1
void func2(int *a){}

返回引用

返回值不能是局部变量(局部变量在生命期结束后会被销毁)
​ (c中生命周期结束后,立马销毁,而在python中垃圾回收机制会在判断之后不使用的情况下再销毁)
func2(&b);

增强的for循环:

在vc6.0中 for(int i=4;i>0;i–) i的作用域为 整个外部作用域如
void main()
{
​ for(int i=4;i>0;i–) //作用域为整个main函数
}
而在vs中 for(int i=4;i>0;i–) i的作用域为 该个for循环内
void main()
{
​ for(int i=4;i>0;i–) //作用域为该个for循环
}


默认参数 从右往左连续

返回值不是函数重载的条件


malloc和free 不会触发构造函数或是析构函数
new和delete 可以

不做特别说明,类的数据成员和成员函数都被认为是private

this指针

  • this 是类成员函数的隐含参数,不是类的数据成员
  • 静态成员无this指针

常函数

  • 常函数不能修改类中的数据成员的值

  • 析构函数和构造函数不能是常函数

  • 常变量只能调用常函数,不能调用普通函数

  • 常对象只能调用常函数,不能调用普通函数

静态成员

  • 是类本身的属性,无对象时也可以直接调用Cstu::sta
  • 静态成员函数只能调用静态数据成员
    类外初始化 不需要static关键字 如: int Cstu::sta = 12;

创建数组

1
2
a = new int[2];
delete[] a;

浅拷贝和深拷贝

  • 系统默认的为浅拷贝
  • 有指针承运啊时得内存拷贝,所以使用深拷贝,
  • 为了避免拷贝构造,运算符重载应该传引用

拷贝构造

何时会调用

1.新建一个对象,并将其初始化为同类现有对象

1
2
3
4
5
6
Cstu a;
- Cstu a1(a);
- Cstu a2 = a;
- Cstu a3 = Cstu(a); //创建了临时对象
- Cstu a4 = new Cstu(a);
- △.赋值并不会发生拷贝构造

2.当程序生成对象副本时

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

- 参数是本类的常引用Cstu(const Cstu&)

- 普通构造函数如果空的话是不执行内容的,拷贝构造空的话是执行内容的
- 默认的复制构造函数,逐个复制非静态成员的值,

## 内联函数inline

- 函数代码少,流程直接,调用频繁,如循环
- 类内定义的都是内联函数(隐式),写inline为显性
- 内联函数的定义一般写在头文件内

- 只在声明位置写inline不管用,定义与声明都要有inline关键字
- 空间换时间,使用频率低时速度快,频率高时,比较占用内存,主要看性价比
- 递归不能是内联函数

## 操作符重载

------

- 为了避免拷贝构造,运算符重载应该传引用或是传地址
- 操作符重载必须有一个类类型的参数
- =、[]、()、->必须是诚邀
- 复合赋值运算符通常是成员
- 改变对象状态的运算符,递增、解引用,通常是成员

### 输出运算符重载:

- 参数1是ostream引用,参数2是对象的常引用
- 必须是类外重载,原因为1
- 输出私有成员时,要用友元

void operator << (ostream& os,const &Csty),os <<st.nAge;
ostream& operator << (ostream& os,const &Csty),os <<st.nAge;

1
2
3
4
5

### 输入运算符重载:

- 参数不匹配用ist.fail()检测
- 输出=> ist>>st.nAge >> st.dbHeight;

istream& operator >>(istream& ist,CStu& st)

1
2
3
4

------

### 前置+ +与后置+ +重载

int operator++(Cstu* st){} =>前置++

int operator++(Cstu* st,int n) =>后置++
{
int a =st.nage;
st.nage +=1;
return a;
}

1
2
3
4

------

类型转换重载

operator int()const{} //无返回值,但有return

1
2
3
4

△.必须在类内。▲.const

## 模板

template
void func(Y a) cout << a << endl;

1
2

模板的具体化:

temlpate <> void func(Node& a){}

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

> 模板具体化的执行优先级高于通用的优先级,



◇.注意,STL头文件没有扩展名.h



------

# CPP

```该类接受2个参数
初始化列表
class CStu
{
int a;
int arr[4];
float b;
//构造函数:
CStu(*float c,int d*):a(2),b(2.2f),arr() #成员初始化顺序只与声明顺序有关,与此处书写顺序无关
{ #新增语法,arr数组全初始化为0

}
}

▲.类必须先初始化成员变量。

​ 。float c和int d 两个变量的作用域仅限于构造函数内.所以要想在整个类中使用该变量,就得将传入的参数初始化赋值给类中的变量。

​ 若有多个构造函数,会执行初始化列表绑定所在的构造函数(构造函数的重载)

数组的赋值:

  • 初始化列表arr()
  • 构造函数中for循环赋值
  • memset(&arr[0],0,16)

△.析构函数没有重载,且不接受参数。对象声明调用周期结束时自动调用。

▲构造函数和析构函数都必须写在public访问控制符下


malloc和new、free和delete区别

  • malloc不会触发构造函数,new可以
  • free不会触发析构函数,delete可以

This指针

指针类型为类的类型。

this不是类的成员。

this指针为成员函数的隐含参数,相当于python类中的self…(所以this指针的作用域为类内部)


常函数

CStu{}
1
2
3
4
5
6
class CStu
{
public:
void show() const #在括号之后
{}
}

◆.析构函数、构造函数不能是常函数

◆.常函数不能修改数据成员(是类的),但可以修改常函数内的变量。

▲常函数的this指针的类型为const CStu*

★常对象(const CStu st)只能调用常函数,不能调用普通函数


静态成员

1
2
3
4
5
6
7
class CStu
{
static int b;
public:
void show() const #在括号之后
{}
}

∷不能在构造函数的初始化列表中初始化,但可以类外初始化

∷类外初始化不用加static,而是int CStu::b = 12;

▲static受访问控制符约束。

调用方法:

1
2
类名作用域:cout<< CStu::b << endl;
对象:

○只有静态常量整型数据才能直接在类中初始化,其他得在初始化列表或者构造函数中赋值(静态数据成员可以类外赋值),普通数据成员不能类外初始化。

●静态成员是跟类一一对应的,跟对象无关。

静态成员函数

他是属于类的属性,不是对象的,即同一个类的所有对象共有一个(可以作为指挥类所有对象的方法)

无this指针

不能调用普通成员,只能调用静态成员


拷贝构造

public:

​ Cstu(const Cstu &a){} 形式。参数是本类的常引用

何时调用:

1
2
3
4
5
6
7
8
9
1.新建一个对象,并将其初始化为同类时:
- Cstu a1(a); #a为一个Cstu对象
- Cstu a2 = a; 将不会再触发构造函数。
- Cstu a3 = Cstu(a); 用a来拷贝构造一个临时对象,再用这个临时对象给a3
- Cstu* a4 = new Cstu(a);
2.当程序生成对象副本时:
函数参数传递对象的值void fun(Cstu a){} (∵当调用这个函数的时候会为这个形参生成空间)
▲有时为了效率要避免这种拷贝构造的产生,解决:传引用
函数返回值 Cstu fun(){ Cstu a; return a;} 返回值为创建了临时对象承接,然后再把临时变量返回。

赋值不会调用:

Cstu s1;

Cstu s2;

s2 = s1;

默认拷贝构造(浅拷贝)

逐个赋值非静态成员,(即默认拷贝构造中是有内容的,默认的构造函数是没有内容的)

内存排布一样,地址不同

深拷贝(涉及类中有指针)

如果是浅拷贝,则两个对象的指针都会指向同一个空间,如果第一个对象被消除后,这个空间就会被delete(free掉),所以第二个对象被删除时再操作(free)这个被释放掉的空间(已经还给系统),就相当于控制野指针,所以会报错。

解决方法1深拷贝:

1
2
3
this->a = new int[2];
memcpy(this->a,b.a,8);
strcpy(...)

解决方法2传引用(不经过拷贝构造):

1
2
3
Cstu& fun(CStu& a)
{ return a; }
fun(a);

解决方法3传地址:

1
2
3
Cstu* fun(CStu* a)
{ return a; }
fun(&a);

inline内联函数

常规函数的调用过程:调用时,根据函数地址,跳到函数代码空间,执行指令,执行完再跳转到调用的位置。

内联函数:将函数代码直接复制到执行部分,不跳转。

比常规函数稍快

占用更多内存(增加代码长度)

▲声明和定义都要加inline 关键字

▲递归不能是内联函数

△.函数代码少时、调用频繁(for循环里)大多用内联函数(常规函数的话,跳转所耗时间占比就大)

▲.类内定义的函数都是内联函数,但如果定义在类外的话加inline为内联函数,不加就不是内联函数。

△.内联函数通常定义在头文件里。


操作符重载

operator为关键字

“operator+”必须有一个类类型的形参;


继承:

继承控制符:

public 父类:父类为什么访问控制符,子类就继承什么样的。

protected 父类:继承之后,父类的public降级为protected,低级或者同级的访问控制符不变(即protectedh和private)

private 父类:继承之后,父类全变为私有。

多态和虚函数

多态:同样的调用有多种结果

通过虚函数调用子类的成员函数,形式为virtual void Show(){} (函数名与子类相同)

具体执行那个子类的函数由父类所指向的子类所决定. CFather* fa = new CSon1;


C++中声明结构体变量不需要‘struct’,struct默认为public,class 默认为private

c静态变量在预处理时声明。

cpp静态成员在类声明时声明。

STL初始化


  • (1): vector v;

    默认初始化,vector为空, size为0,表明容器中没有元素,而且 capacity 也返回 0,意味着还没有分配内存空间。

  • (2): vector v2(v);

    vector v2= v;

    两种方式等价 ,ilist2 初始化为ilist 的拷贝,ilist必须与ilist2 类型相同,也就是同为int的vector类型,ilist2将具有和ilist相同的容量和元素

  • (3): vector ilist = {1,2,3.0,4,5,6,7};

    vector ilist {1,2,3.0,4,5,6,7};

初始化为列表中元素的拷贝,列表中元素必须与ilist的元素类型相容

  • (4): vector ilist3(ilist.begin()+2,ilist.end()-1);

    初始化为两个迭代器指定范围中元素的拷贝,范围中的元素类型必须与ilist3 的元素类型相容

  • (5): vector ilist4(7);

    默认值初始化,ilist4中将包含7个元素,每个元素进行缺省的值初始化,对于int,也就是被赋值为0,

  • (6):vector ilist5(7,3);

    指定值初始化,ilist5被初始化为包含7个值为3的int


1
2
std::vector<int> idxs中
for(int i : idxs) ====> for i in indx ..... i 为idxs中元素

Author: Mrli

Link: https://nymrli.top/2019/07/13/C-学习笔记/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
利用wireshark抓取TCP的整个过程分析[转]
NextPost >
通过XDRP实现Windows远程访问ubuntu桌面
CATALOG
  1. 1. C++学习笔记
    1. 1.1. sprintf
    2. 1.2. 引用
    3. 1.3. 增强的for循环:
    4. 1.4.
    5. 1.5. this指针
    6. 1.6. 常函数
    7. 1.7. 静态成员
    8. 1.8. 创建数组
    9. 1.9. 浅拷贝和深拷贝
    10. 1.10. 拷贝构造
    11. 1.11. malloc和new、free和delete区别
    12. 1.12. This指针
    13. 1.13. 常函数
    14. 1.14. 静态成员
    15. 1.15. 静态成员函数
    16. 1.16. 拷贝构造
      1. 1.16.1. 默认拷贝构造(浅拷贝)
      2. 1.16.2. 深拷贝(涉及类中有指针)
    17. 1.17. inline内联函数
    18. 1.18. 操作符重载
    19. 1.19. 继承:
    20. 1.20. 多态和虚函数
      1. 1.20.1. 多态:同样的调用有多种结果
    21. 1.21. STL初始化