C++ 命名空间、域、缺省参数、函数重载、引用、auto、内联函数的知识点+完整思维导图+基本练习题+深入细节+通俗易懂建议收藏(二)

简介: C++ 命名空间、域、缺省参数、函数重载、引用、auto、内联函数的知识点+完整思维导图+基本练习题+深入细节+通俗易懂建议收藏(二)

6.引用

知识点:

6.1引用的定义:

引用不是新定义一个变量,而是给已存在变量取了一个别名,在语法层面上编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。(就像绰号,叫真名和绰号是一样的)


引用的基本语法:引用的对象的类型+&+引用名 =引用的对象

//整形

   int a = 0;

   int& b = a;

//指针

   int * ptr = NULL;

   int*& rp = ptr;

image.png

细节(注意点):

1、在创建引用定义时必须初始化:int& b = a;

image.png

2、一个变量可以用多个引用(一个人在每个阶段都可能有不同的绰号,但都是指同一个人)

int main()
{
    int a = 0;
    int& b = a;
    int& c = a;
// b 、 c 都是a的引用
}

3、只能一开始进行引用的初始化指定引用对象、后面无法进行修改。(后面修改也只是赋值操作)

6.2使用场景:

引用做参数

输出型参数 ,像我们之前在C语言写链表来举例,当需要改变phead时就需要传一个二级指针,但此时我们用到了引用就不用再使用二级指针。

image.png

提高效率,因为引用的物理意义是一个变量的别名,在传参时并不用为其开辟栈帧所以可以提高一定的效率。

引用做返回值

但要小心,引用返回的对象不能在栈里面,否则当出栈帧时就会导致非法访问,一般用于静态区,堆区上的

可以修改返回值

提高效率,当引用做返回值的时候,返回的就是一个变量的别名,此时在传递回去的过程中就不需要创建临时变量(放到寄存器)的返回,这样就能减少损耗

练习:

1. 通过引用来进行数值的交换(在C语言中我们需要用到指针才能完成)

//指针时:void  Swap(int * a, int * b)
void Swap(int& a, int& b)//此时的a 、 b 是参数的引用
{
  int tmp = a;
  a = b;
  b = tmp;
}
int main()
{
  int a = 10; 
  int b = 20;
  cout << a << ' ' << b << endl;
  Swap(a,b);
  cout << a << ' ' << b << endl;
  return 0;
}

image.png

6.3常引用问题

知识点:

对常数的引用时要注意的点(此处主要讨论的是const修饰的常变量)


在引用时,引用的类型相对于引用对象的类型来说只能平移或者降低(注意看注释,若看不懂后面有一个附加知识点)

image.png

一种特殊情况:

image.png

附:当需要整形提升/截断时他们在赋值前都会先创建一个临时变量,把这个提升、截断后的值先放到这个临时变量(寄存器)内,再把这个临时变量的值放到所要赋值的空间中(这样就避免把被赋值的值改变)

image.png

就是因为一个临时变量具有常性,所以需要加上const来修饰

image.png

临时变量具有常性  ,同理对于函数返回时也是一样的,当我们返回一个临时变量时是有常性的所以需要用到常变量const来修饰

image.png

此时我们还需要注意的点是:当返回值是引用时就不会创建临时变量了。


6.4引用的总结:

知识点:

在语法层面上我们理解的是引用并不开辟空间,但是在底层来说其原理和指针一样也是需要开辟空间的(我们理解了解底层即可平时就记住语法层面 : 就像老婆饼里没老婆)

image.png

底层逻辑一样

指针和引用的区别

没有NULL引用这种概念,而指针有空指针的概念

sizeof中指针和引用有不同,引用的结果就是引用对象类型的大小,而指针时地址的大小

引用和指针的加减不一样

有多级指针,没有多级引用

指针需要解引用,而引用操作系统自动处理了

引用比指针更加安全(指针可能会有野指针的问题)

7.关键字auto

知识点:

一种可以根据左边表达式自动推到出其类型然后定义给变量


具体就用实例来描述:

int main()
{
    int x = 10;
    auto a = &x;//因为地址,所以auto是指针类型
    auto* b = &x;
    auto& c = x;
    cout << typeid(a).name() << endl;//int * 
    cout << typeid(b).name() << endl;//int *
    cout << typeid(c).name() << endl;//int (引用的类型不用加上&)
    *a = 20;
    *b = 30;
    c = 40;
    return 0;
}

此处的 auto 和 auto * 其实是一样的

附:typeid(变量名). name()    这个可以识别输入变量的类型


细节(注意点):

auto的价值是:一般适用于对一些比较长的类型进行auto自动识别化

使用auto定义变量必须有初始化(在编译阶段编译器根据初始化表达式推倒出表示的类型,其实auto并不是一个类型,在编译后会将其改成实际的类型如#define定义宏类似)

image.png

auto也可以一次性声明多个变量,但是这几个变量类型必须是相同的(因编译器只对一个类型进行推导)

image.png

auto不能用在形参部分来识别类型(编译器无法对参数的实际类型进行推导)(c++14往后的可以作返回值)

image.png

auto不能直接对数组进行声明

image.png

8.范围for

知识点:

对数组进行遍历

语法: for (数组类型  变量名  : 数组名)

细节(注意点):

当把一个数组传进函数时其本质是一个指针(数组名首元素地址)所以在该函数内是不能去使用这个范围for的

image.png

通过练习描述:

int main()
{
    int a[] = { 1,2,3,3,4,5,6,7,8,9,10 };
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        cout << a[i] << ' ';
    }
    cout << endl;
    for (auto x : a)// for (数组类型  语法for的变量名  : 数组名)
    {
        cout << x << ' ';
    }
    cout << endl;
}

此时只是依次将数组a中的数据拷贝给x(所以拷贝的无法改变其数组内容)

若想改变在数组a的值就需要加上引用 如下:

image.png

9.内联函数

知识点:

内联函数的设立是为了减少一些重复创建栈帧的开销,以inline修饰的函数被叫做内联函数,该函数不会去开辟栈帧,会直接在调用内联函数的地方展开使用。(在C语言中这种简单重复使用的函数一般会用宏来实现,但宏也有其自己的缺点所以c++进行优化创造出来内联函数)


细节:

内联函数的具体展现:

当没有使用内联函数时:就会正常的去调用函数,开辟栈帧...

image.png

image.png

当使用内联函数后:调用内联函数的地方会直接展开使用(此时就没用call调用函数)。

image.png

image.png

内联函数对于编译器来说是一个建议性的操作,最后是否实现取决于编译器(对于编译器来说:如果是递归函数/比较长函数他们就不会同意变成内联函数)

注意对于一个较大的函数来说,不能使用内联函数,因为内联函数会导致程序的指令变多(直接正常调用此时指令就在函数内并不会变多,而内联函数会将函数展开就会导致指令反而变多,如:假如一个函数的指令是50个,然后又100处地方要调用这个函数,此时对于直接调用函数的指令就是100 + 50 ,假如是内联函数就变成了 100 * 50)

假如你要分源管理,此时内联函数不要声明和定义分离(因为内联函数不需要要调用就不会生成地址而这样就不会进入到符号表,若声明和定义分开就会导致链接错误找不到,直接就写定义即可)

10.指针空值nullptr

       在c++中NULL并不表示空指针而是表示为0(NULL实际是一个宏代表0),所以在c++11中就新引入了一个关键字表空指针nullptr        


本章完。预知后事如何,暂听下回分解。

相关文章
|
4月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
4月前
|
安全 程序员 编译器
【C++】如何巧妙运用C++命名空间:初学者必备指南
【C++】如何巧妙运用C++命名空间:初学者必备指南
|
5月前
|
安全 程序员 编译器
C++ 11新特性之auto和decltype
C++ 11新特性之auto和decltype
57 3
|
4月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
5月前
|
程序员 C++ 容器
C++编程基础:命名空间、输入输出与默认参数
命名空间、输入输出和函数默认参数是C++编程中的基础概念。合理地使用这些特性能够使代码更加清晰、模块化和易于管理。理解并掌握这些基础知识,对于每一个C++程序员来说都是非常重要的。通过上述介绍和示例,希望能够帮助你更好地理解和运用这些C++的基础特性。
58 0
|
5月前
|
C语言 C++
C++(六)Namespace 命名空间
命名空间(Namespace)是为了解决大型项目中命名冲突而引入的机制。在多库集成时,不同类库可能包含同名函数或变量,导致冲突。C++通过语法形式定义了全局无名命名空间,并允许对全局函数和变量进行作用域划分。命名空间支持嵌套与合并,便于协同开发。其使用需谨慎处理同名冲突。
|
25天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
64 19
|
25天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
45 13
|
25天前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
47 5
|
25天前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
36 5