C++笔记(11-20)

本文详细解释了C++中的空指针、野指针概念,以及常量指针和指针常量的区别,还介绍了引用、数组、内存管理(newdelete)和面向对象编程中的构造函数和析构函数。
摘要由CSDN通过智能技术生成

C++笔记(11-20)条


十一、空指针&野指针:指针都占8字节32位

1、空指针:没有存储任何内存地址的指针变量。
如:int* p = NULL;

2、野指针:存储有一个内存地址,但此内存地址指向的空间可能不存在,或没有访问权限。
如随便设置一个地址:int* p = (int*)0x1234;
访问空指针和野指针的*p是会出现问题的。

十二、常量指针(常量的指针 *p)&指针常量(指针是常量 p)

1.常量指针(常量的指针),其中*p 是常量,不可修改

如下:const 修饰 (* p)(常量)

int a = 20;
int b = 30;
const int* p = &a;  // *p = 90,这样的操作是不可以修改的
cout << *p << endl; 
a = 90;              // *p = 90不行,但直接改int a可以
cout << *p << endl;
p = &b;  // *p不能修改,但p可以修改,即可以重新指向其他变量的地址
cout << *p << endl;

总结:在const int* p = &a中,
①*p不可修改
②a可以修改,*p跟着被修改
③p可以修改,即指向其他地址

补充:
const int a = 20;
int p = &a; //INVALID
const int
p = &a; //VALID
C++禁止将const 地址赋给非const 的指针。如果非要这样做,可以通过const_cast 强制转换。

2.指针常量(指针是常量),其中 p是常量,不能修改

如下:const 修饰( p)(指针)

int a = 10;
int b = 20;
int* const p = &a;         // p = &b ,这样的操作不行,因为p是常量
cout << p << " , "<< * p << endl;
a = 90;                    // a = 90 等效于 *P = 90
cout << a<< " , " << *p << endl;

总结:在int* const p = &a; 中
①p不可以修改,即不能指向其他地址
②*p可以修改,a跟着被修改
③a可以修改,*p跟着被修改

十三、引用:取别名,本质是指针常量

一、基本语法:type& newname = oldname
int a = b; // 将 b 的值copy给 a, a、b不同地址
int& b = a; // 给a取了个别名b,a和b 指向同一个地址

二、引用在函数中的运用:
int function(int& a, int& b)
如上,可以在函数体中,通过修改形参的值更改实参的值。

三、常量引用(常引用)
void function( const int& a):const 修饰 & a,a 是常量
防止修改形参的值更改了实参的值
如:
int b = 10;
function(b) // a和b是同一个变量,只是在函数中,无法修改b,也就是无法修改a

十四、数组

一、当数组作为实参传递时,传递的只是首元素的地址,所以还要传递数组的长度。

二、数组遍历
①下标遍历

int arr[10] = {0};
int len = sizeof(arr) / sizeof(int);
for (int i = 0 ; i < len ; i ++ ){}

②元素迭代

for (int tmp : arr){}
// 无法通过修改tmp的值来修改arr的值

十五、new & delete

参考:
https://blog.csdn.net/weixin_70273825/article/details/134327992

int arr1[11] = { 0,1,2,3,4,5,6,7,8,9 };
cout << arr1 << endl; // arr1 就是首地址,首地址[i] 就是数组元素
int* pint = new int(6);
cout << *pint << endl;
int* p = new int[10] {48, 4, 5, 67, 899, 333}; // 遍历数组p,不能用元素迭代
for (int i = 0; i < 10; i++) {
	cout << p[i] << " ";
}
cout << endl;
delete pint;
delete[]p;

1.new

在这里插入图片描述

2.delete

在这里插入图片描述

3.new[]

在这里插入图片描述

4.[]delete

在这里插入图片描述

十六、面向对象与面向过程的区别

  1. 面向过程:亲力亲为
    面向过程是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数。

  2. 面向对象:术业有专攻
    面向对象是一种以“对象”为中心的编程思想,把要解决的问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个对象在整个解决问题的步骤中的属性和行为。

十七、三种对类成员的访问权限

在C++中,权限通常指的是对类成员的访问权限。C++有三种访问权限:

public:公共权限,表示在类外部可以直接访问。

protected:受保护的权限,类外无法访问,表示只能由当前类及其派生类(子类)访问。

private:私有权限,表示只能由类内部访问,不能被类外部访问。

默认情况下,如果不指定访问权限,C++会将成员声明为private。

十八、静态static(共用)

一、类的静态成员
(1)在类中用static修饰成员,则该成员是静态成员;
(2)静态成员是属于类本身的,所有类的对象共享;
(3)类的对象都可以访问静态成员,但是所有类的成员访问的静态成员都是同一份静态成员;(一变全变)
(4)静态成员在类内部声明时加static声明,在类外定义静态成员时无需添加static修饰;

二、静态成员初始化
①一般是类内定义,类外进行初始化赋值
②如果是静态常量,且数据类型是整型(int,short,long,long long,char,bool),允许在定义时就初始化赋值,也可以类外赋值。

三、访问静态成员
①使用类来访问
②使用对象来访问

class MyClass {
    public:
    static int count;   //类内定义
    const static int score = 99;  //静态常量在定义时就初始化赋值
    MyClass() {   // 构造函数
        count++;
    }
};
int MyClass::count = 0; // 类外进行初始化赋值
int main() {
    MyClass obj1;
    cout << MyClass::score << endl;    // 使用类来访问
    cout << MyClass::count << endl;    //使用类来访问
    cout << obj1.count << endl;        // 使用对象来访问
    obj1.count = 78;                 //MyClass 类的count都为78
    return 0;
}

十九、构造函数,要public权限

一、构造函数的作用:初始化对象的数据成员

二、定义:以类名作为函数名,无返回类型,可以重载

三、构造函数的分类:
①无参构造函数,自己不写,函数默认自动生成
②一般构造函数,可以有多个,创建对象时根据传入的参数不同调用不同的构造函数,可以配合列表初始化
③复制构造函数(拷贝构造函数)

四、构造函数的调用
①显式调用
Coordinate c1 = Coordinate();
Coordinate c2 = Coordinate(1.2, 3.2);
等效如下:
Coordinate c1;
Coordinate c2(1.2, 3.2);
②隐式调用:单个参数也可以不需要{}
Coordinate c1 = {};
Coordinate c2 = { 1.2, 3.2 };

五、explicit
explicit关键字在C++中是用来修饰类的构造函数的,它的目的是用来防止不应允许的类型转换,杜绝隐式调用。

代码示例:

class Coordinate
{
public:
  //无参构造函数,杜绝隐式调用
   explicit  Coordinate()
    {
        c_x = 0;
        c_y = 0;
    }
    // 一般构造函数  + 列表初始化
    Coordinate(double x, double y) :c_x(x), c_y(y) {}   
    
   //拷贝构造函数
    Coordinate(const Coordinate& c)
    {
        // 复制对象c中的数据成员
        c_x = c.c_x;
        c_y = c.c_y;
    }
}

二十、析构函数

一、作用:析构函数完成的是对象中资源的清理工作。通常是对对象中动态开辟的空间进行清理。

二、析构函数特性:
1.析构函数的函数名是 ~类名
2.析构函数无参数无返回值
3.一个类中只能有一个析构函数,析构函数不支持重载
4.若未显式定义析构函数,编译器会默认生成一个析构函数
5.析构函数由编译器在[对象生命周期]结束时自动调用

代码示例:在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值