C++八股文基础(一)——指针和引用的区别? 常量指针和指针常量的区别?什么是函数指针,如何定义和使用场景? 函数指针和指针函数的区别?静态局部变量\全局变量\局部变量的区别和使用场景 等

目录

指针和引用的区别

数据类型

整型 short int long 和 long long

无符号类型

常量指针和指针常量的区别

什么是函数指针,如何定义和使用场景?

函数指针和指针函数的区别

struct和Class的区别

静态局部变量\全局变量\局部变量的区别和使用场景

C++强制类型转换

1. static_cast

2. dynamic_cast

3. reinterpret_cast

4. const_cast


指针和引用的区别

指针存放某个对象的地址,其本身就是变量(命了名的对象),本身就有地址,所以可以有指向指针的指针;可变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变

引用就是变量的别名,从⼀⽽终,不可变,必须初始化

不存在指向空值的引⽤,但是存在指向空值的指针

1. 定义和声明:

指针是⼀个变量,其值是另⼀个变量的地址。声明指针时,使⽤ * 符号。

int x = 10; 
int *ptr = &x;

引用是⼀个别名,它是在已存在的变量上创建的。在声明引⽤时,使⽤ & 符号。

int y = 20;
int &ref = y;

2. 使用和操作:

指针: 可以通过解引⽤操作符 * 来访问指针指向的变量的值,还可以通过地址运算符 & 获取变量的地址。

int value = *ptr; // 获取指针指向的值
int address = &x; // 获取变量 x 的地址

引用: 引⽤在声明时被初始化,并在整个⽣命周期中⼀直引⽤同⼀个变量。不需要使⽤解引⽤操作符,因为引⽤本身就是变量的别名

int newValue = ref; // 获取引⽤的值

3. 空值和空引用:

指针可以为空(nullptr)表示不指向任何有效的地址。

引用必须在声明时初始化,并且不能在后续改变引⽤的绑定对象。因此,没有空引⽤的概念

4. 可变性:

指针: 可以改变指针的指向,使其指向不同的内存地址。

引用: ⼀旦引⽤被初始化,它将⼀直引⽤同⼀个对象,不能改变绑定。

5. 用途:

指针: 通常⽤于动态内存分配、数组操作以及函数参数传递。

引用: 通常⽤于函数参数传递、操作符重载以及创建别名。

数据类型

整型 short int long 和 long long

C++ 整型数据⻓度标准

short ⾄少 16 位

int ⾄少与 short ⼀样⻓

long ⾄少 32 位,且⾄少与 int ⼀样⻓

long long ⾄少 64 位,且⾄少与 long ⼀样⻓

在使⽤8位字节的系统中,1 byte = 8 bit

很多系统都使⽤最⼩⻓度,short 为 16 位即 2 个字节,long 为 32 位即 4 个字节,long long 为 64 位即 8 个字 节,int 的⻓度较为灵活,⼀般认为 int 的⻓度为 4 个字节,与 long 等⻓。 可以通过运算符 sizeof 判断数据类型的⻓度。例如:

cout << "int is " << sizeof (int) << " bytes. \n";
cout << "short is " << sizeof (short) << " bytes. \n";

头⽂件climits定义了符号常量:例如:INT_MAX 表示 int 的最⼤值,INT_MIN 表示 int 的最⼩值。

无符号类型

即为不存储负数值的整型,可以增⼤变量能够存储的最⼤值,数据⻓度不变。

int 被设置为⾃然⻓度,即为计算机处理起来效率最⾼的⻓度,所以选择类型时⼀般选⽤ int 类型。

常量指针和指针常量的区别

  • 常量指针是指针所指向的内容是常量,指针本身可变。
  • 指针常量是指针本身是常量,所指的内容可变。
  • 在常量指针中, const 关键字位于 * 之前。
  • 在指针常量中, const 关键字位于 * 之后。

常量指针是指指针所指向的内容是⼀个常量,即指针所指向的内容不能被修改,但指针本身的值(地址)可以被修改

int x = 10;
int y = 20;
// 定义:const int *ptr = &x; 或 int const *ptr = &x; 
const int *ptr = &x; // 常量指针,不可以修改指针所指向的内容,可修改指针的值
// *ptr = 30; // 错误,不能修改指针所指向的内容
ptr = &y; // 正确,可修改指针的值

指针常量是指指针本身是⼀个常量,即指针的值(地址)不能被修改,但它所指向的内容可以被修改

int x = 10;
int y = 20;
int *const ptr = &x; // 指针常量,可以修改指针所指向的内容,不能修改指针的值
*ptr = 30; // 正确,可以修改指针所指向的内容
// ptr = &y; // 错误,不能修改指针的值

什么是函数指针,如何定义和使用场景?

函数指针是指向函数的指针变量。它可以⽤于存储函数的地址,允许在运⾏时动态选择要调⽤的函数。

int add(int a, int b) {
    return a + b;
}
int subtract(int a, int b) {
    return a - b;
}
int main() {
    // 定义⼀个函数指针,指向⼀个接受两个int参数、返回int的函数
    // 返回类型 (*指针变量名)(参数列表)
    int (*operationPtr)(int, int);
    // 初始化函数指针,使其指向 add 函数
    operationPtr = &add;
    // 通过函数指针调⽤函数
    int result = operationPtr(10, 5);
    cout << "Result: " << result << endl;
    // 将函数指针切换到 subtract 函数
    operationPtr = &subtract;
    // 再次通过函数指针调⽤函数
    result = operationPtr(10, 5);
    cout << "Result: " << result << endl;
    return 0;
}

使⽤场景:

  1. 回调函数: 函数指针常⽤于实现回调机制,允许将函数的地址传递给其他函数,以便在适当的时候调⽤。
  2. 函数指针数组: 可以使⽤函数指针数组实现类似于状态机的逻辑,根据不同的输⼊调⽤不同的函数。
  3. 动态加载库: 函数指针可⽤于在运⾏时动态加载库中的函数,实现动态链接库的调⽤。
  4. 多态实现: 在C++中,虚函数和函数指针结合使⽤,可以实现类似于多态的效果。
  5. 函数指针作为参数: 可以将函数指针作为参数传递给其他函数,实现⼀种可插拔的函数⾏为。
  6. 实现函数映射表: 在⼀些需要根据某些条件调⽤不同函数的情况下,可以使⽤函数指针来实现函数映射表。

函数指针和指针函数的区别

函数指针是指向函数的指针变量。可以存储特定函数的地址,并在运⾏时动态选择要调⽤的函数。通常⽤于回调函数、动态加载库时的函数调⽤等场景。

int add(int a, int b) {
    return a + b;
}
int (*ptr)(int, int) = &add; // 函数指针指向 add 函数
int result = (*ptr)(3, 4); // 通过函数指针调⽤函数

指针函数是⼀个返回指针类型的函数,⽤于返回指向某种类型的数据的指针。

int* getPointer() {
    int x = 10;
    return &x; // 返回局部变ᰁ地址,不建议这样做
}

struct和Class的区别

  • 通常, struct ⽤于表示⼀组相关的数据,⽽ class ⽤于表示⼀个封装了数据和操作的对象,在实际使⽤中,可以根据具体的需求选择使⽤ struct class 。如果只是⽤来组织⼀些数据,⽽不涉及复杂的封装和继承关系, struct 可能更直观;如果需要进⾏封装、继承等⾯向对象编程的特性,可以选择使⽤ class
  • struct 结构体中的成员默认是公有的(public)。类中的成员默认是私有的(private)。
  • struct 继承时默认使⽤公有继承。class 继承时默认使⽤私有继承。
  • 如果结构体没有定义任何构造函数,编译器会⽣成默认的⽆参数构造函数。如果类没有定义任何构造函数,编译器也会⽣成默认的⽆参数构造函数。
// 使⽤ struct 定义
struct MyStruct {
    int x; // 默认是 public
    void print() {
        cout << "Struct method" << endl;
    }
};
// 使⽤ class 定义
class MyClass {
public: // 如果省略,默认是 private
    int y;
    void display() {
        cout << "Class method" << endl;
    }
};

静态局部变量\全局变量\局部变量的区别和使用场景

1. 静态局部变量

  • 作⽤域: 限定在定义它的函数内。
  • ⽣命周期: 与程序的⽣命周期相同,但只能在定义它的函数内部访问。
  • 关键字: 使⽤ static 关键字修饰。
  • 初始化: 仅在第⼀次调⽤函数时初始化,之后保持其值。

当希望在函数调⽤之间保留变量的值,并且不希望其他函数访问这个变量时,可以使⽤静态局部变量。

void exampleFunction() {
    static int count = 0; // 静态局部变量
    count++;
    cout << "Count: " << count << endl;
}
// 注意:当我们多次调用 exampleFunction() 函数时,count 变量的值会累加,而不是每次都从 0 开始。

2. 全局变量 

  • 作⽤域: 整个程序。
  • ⽣命周期: 与程序的⽣命周期相同。
  • 关键字: 定义在全局作⽤域,不使⽤特定关键字。

当多个函数需要共享相同的数据时,可以使⽤全局变量。

int globalVar = 10; // 全局变量
void function1() {
    globalVar++;
}
void function2() {
    globalVar--;
}

3. 局部变量

  • 作⽤域: 限定在定义它的块(⼤括号内)。
  • ⽣命周期: 在块结束时销毁。
  • 关键字: 定义在函数、语句块或类的成员函数中。

当变量只在某个特定作⽤域内有效,并且不需要其他作⽤域访问时,可以使⽤局部变量。

总结

  • 静态局部变量⽤于在函数调⽤之间保留变量的值。
  • 全局变量适⽤于多个函数需要共享的数据。
  • 局部变类适⽤于仅在特定作⽤域内有效的情况。

C++强制类型转换

关键字:static_cast dynamic_cast reinterpret_cast const_cast 

1. static_cast

没有运⾏时类型检查来保证转换的安全性

进⾏上⾏转换(把派⽣类的指针或引⽤转换成基类表示)是安全的;

进⾏下⾏转换(把基类的指针或引⽤转换为派⽣类表示),由于没有动态类型检查,所以是不安全的。

使⽤:

  1. ⽤于基本数据类型之间的转换,如把int转换成char。
  2. 把任何类型的表达式转换成void类型。

2. dynamic_cast

在进⾏下⾏转换时,dynamic_cast具有类型检查(信息在虚函数中)的功能,⽐static_cast更安全。

转换后必须是类的指针、引⽤或者void*,基类要有虚函数,可以交叉转换。

dynamic本身只能⽤于存在虚函数的⽗⼦关系的强制类型转换;对于指针,转换失败则返回nullptr,对于引⽤,转换失败会抛出异常。

3. reinterpret_cast

可以将整型转换为指针,也可以把指针转换为数组;可以在指针和引⽤⾥进⾏肆⽆忌惮的转换,平台移植性⽐价差。

4. const_cast

常量指针转换为⾮常量指针,并且仍然指向原来的对象。常量引⽤被转换为⾮常量引⽤,并且仍然指向原来的对象。去掉类型的const或volatile属性。

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J^T

谢谢帅哥/美女

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值