CPLUSPLUSTHINGS学习笔记(持续更新)

前言

最近发现一个很有用的C++学习仓库CPlusPlusThings,这是中文的,是作者自己学习的时候做的笔记,能够非常好的巩固基础知识。自己学习主要是在macos和windows上,偶尔能遇到两边结果不一样的问题。下面我将根据仓库顺序,写下自己的笔记。

基础

const关键字

const修饰变量

1.非const变量默认为extern。要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern。未被const修饰的变量不需要extern显式声明!而const常量需要显式声明extern,并且需要做初始化!因为常量在定义后就不能被修改,所以定义时必须初始化。
2.如const位于 * 的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于 * 的右侧,const就是修饰指针本身,即指针本身是常量
3.1)对于指向常量的指针,不能通过指针来修改对象的值。
2)不能使用void指针保存const对象的地址,必须使用const void类型的指针保存const对象的地址。
3)允许把非const对象的地址赋值给const对象的指针
可以常量指针指向变量,但指针不可以修改变量值
在这里插入图片描述
不能变量指针指向常量
在这里插入图片描述
4)如果要修改指针所指向的对象值,必须通过其他方式修改,不能直接通过当前指针直接修改.
在这里插入图片描述
在这里插入图片描述

函数中的const

一..参数为引用,为了增加效率同时防止修改。
因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为void func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临时对象。
重要知识点:函数在接收传递的参数时,都会在函数体内产生参数类型的临时对象复制参数(在传对象的时候很重要)

小结:
1.对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将void func(A a) 改为void func(const A &a)。
2.对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void func(int x) 不应该改为void func(const int &x)。

类中的const

  1. 对于类中的const成员变量必须通过初始化列表进行初始化。
  2. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数. const对象默认调用const成员函数
  3. static静态成员变量不能在类的内部初始化。在类的内部只是声明,定义必须在类定义体的外部,通常在类的实现文件中初始化。

this指针

  1. this指针的用处:
    一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。 
    例如,调用date.SetMonth(9) <===> SetMonth(&date, 9),this帮助完成了这一转换
  2. this指针的使用:
    一种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;另外一种情况是当参数与成员变量名相同时,
    如this->n = n (不能写成n = n)
  3. this指针程序示例:
    this指针存在于类的成员函数中,指向被调用函数所在的类实例的地址。   根据以下程序来说明this指针
#include <stdio.h>  
class Point{   
int x, y;   
public:   
	Point(int a, int b) { x=a; y=b;}   
	void MovePoint( int a, int b){ x+=a; y+=b;}   
	void print(){ cout<<"x="<  
};   

void main( )   {   
Point point1( 10,10);   
point1.MovePoint(2,2);   
point1.print( ); 
}   

当对象point1调用MovePoint(2,2)函数时,即将point1对象的地址传递给了this指针。   
MovePoint函数的原型应该是 void MovePoint( Point *this, int a, int b);第一个参数是指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的。这样point1的地址传递给了this,所以在MovePoint函数中便显式的写成:void MovePoint(int a, int b) { this->x +=a; this-> y+= b;}   即可以知道,point1调用该函数后,也就是point1的数据成员被调用并更新了值。即该函数过程可写成 point1.x+= a; point1. y + = b;

函数和指针

1)指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针
类型标识符 *函数名(参数表)
int *f(x,y); 声明一个指针函数
首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。
float *fun(); fun函数的返回类型为指向float类型的指针
float *p; 定义float类型指针P
p = fun(a); p的地址更新为fun(a)的返回值。

2)函数指针是指向函数的指针变量,他的本质是一个指针变量。
类型说明符 (*函数名)(参数)
1int (*f) (int x);声明一个函数指针
f=func; 将func函数的首地址赋给指针f

其实**这里不能称为函数名,应该叫做指针的变量名。**这个特殊的指针指向一个返回整型值的函数。指针的声明必须和它指向函数的声明保持一致。
其主要的区别是一个是指针变量,一个是函数
形式1:返回类型(*函数名)(参数表)

#include <iostream>
using namespace std;
//定义一个函数指针pFUN,它指向一个返回类型为char,有一个整型的参数的函数
char (*pFun)(int);
//定义一个返回类型为char,参数为int的函数
//从指针层面上理解该函数,即函数的函数名实际上是一个指针,
//该指针指向函数在内存中的首地址
char glFun(int a)
{
    cout << a;
    //return a;
}
int main(){
//将函数glFun的地址赋值给变量pFun
    pFun = glFun;
//*pFun”显然是取pFun所指向地址的内容,当然也就是取出了函数glFun()的内容,然后给定参数为2。
    (*pFun)(2);
    return 0;
}

*形式2:typedef 返回类型(新类型)(参数表)

typedef char (*PTRFUN)(int); 
PTRFUN pFun; 
char glFun(int a){ return;} 
void main() { 
    pFun = glFun; 
    (*pFun)(2); 
} 

typedef的功能是定义新的类型。第一句就是定义了一种PTRFUN的类型,并定义这种类型为指向某种函数的指针,这种函数以一个int为参数并返回char类型。后面就可以像使用int,char一样使用PTRFUN了。
第二行的代码便使用这个新类型定义了变量pFun,此时就可以像使用形式1一样使用这个变量了。

函数调用就是寻址

在这里插入图片描述
1对函数名的取地址&可加可不加
在这里插入图片描述
2.类型的意思:void表示函数无返回值;(*)代表函数地址也就是当前地址值;()函数的参数表
在这里插入图片描述
在这里插入图片描述

类的大小

• 空类的大小为1字节
• 一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。
• 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小。
• 普通继承,派生类继承了所有基类的函数与成员,要按照字节对齐来计算大小
• 虚函数继承,不管是单继承还是多继承,都是继承了基类的vptr。(32位操作系统4字节,64位操作系统 8字节)!
• 虚继承,继承基类的vptr。
知识补充:字节对齐

struct test {
char x1;       	1字节
short x2;		2
float x3;		4
char x4;		1
};

在这里插入图片描述
因为结构体中最长的是float4字节,故为了字节对齐,编译器在后面补了3字节,故Sizeof(test)= 12 byte。
字节对齐原理:
1.存放地址的第一位必须是类型大小的倍数(地址起始位%大小=0),不是就空几位往后找。
2.根据结构或者类内占用字节最多的类型进行补充。
Int 4字节 则就补充到4的倍数:4,8,12,16等
Short 2字节 就补充到2的倍数:2,4,6,8等

struct A {
    int a;
    char b;
    short c;
};
struct B {
    char b;
    int a;
    short c;
};

在这里插入图片描述
特别补充:

在这里插入图片描述
在这里插入图片描述
sizeof(C)=12 //类不算基本类型所以不是根据类A的8字节对齐,而是根据类A中的int类型,4字节对齐。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值