首页 > 编程语言 >大二上 数据结构与算法笔记 20241024

大二上 数据结构与算法笔记 20241024

时间:2024-10-24 14:59:13浏览次数:7  
标签:数据结构 函数 int register C++ 编译器 inline 20241024 大二

一.inline

在 C 和 C++ 编程语言中,inline 关键字是一种函数修饰符,用于建议编译器在编译时将函数的代码直接插入到每个函数调用的地方,而不是进行常规的函数调用。这样做的目的是减少函数调用的开销,尤其是在函数体较小且调用频繁的情况下。

作用和优点:

  1. 减少函数调用开销:通过将函数代码直接插入到调用点,避免了函数调用的额外开销,如参数传递、栈帧的创建和销毁等。
  2. 提高程序运行效率:对于小型函数,inline 可以提高程序的运行效率,因为编译器可以优化掉函数调用的额外开销。
  3. 编译器优化:使用 inline 函数可以让编译器有更多的机会进行优化,因为它可以在编译时看到函数的完整定义。

注意事项:

  1. 编译器的自由裁量:尽管你可以使用inline来建议编译器内联函数,但编译器有权决定是否实际进行内联。编译器会根据函数的大小、复杂度以及调用频率等因素来决定是否内联。
  2. 代码膨胀:过度使用inline可能会导致代码膨胀,因为函数的代码会在每个调用点被复制,这可能会增加程序的总大小。
  3. 调试:使用 inline 函数可能会使得调试变得更加复杂,因为函数的代码在多个地方被复制,这可能会影响调试器的断点设置和错误定位。

使用示例:

inline int add(int a, int b) {
return a + b;
}

在这个例子中,add 函数被声明为 inline 函数,编译器会尝试在每个调用 add 的地方直接插入其代码,而不是进行常规的函数调用。

结论:

inline 是一种有用的函数修饰符,可以在适当的场景下提高程序的运行效率。然而,它并不是银弹,需要根据实际情况谨慎使用。在现代编译器中,即使没有显式声明 inline,编译器也会自动进行内联优化。

二.递归函数中用局部变量

写递归函数的时候,递归时尽量在函数内部定义一个局部变量来用,不使用整体变量进行递归。
全局变量在递归调用中被修改,可能导致在不同的递归层次中出现冲突。每次递归调用都应该使用局部变量来避免这种情况。

三.register int的应用

register int 是 C 和 C++ 编程语言中的一个概念,用于建议编译器将变量存储在 CPU 的寄存器中,而不是内存中。寄存器是 CPU 内部的一小部分高速存储区域,访问速度远远快于主内存。因此,将频繁访问的变量存储在寄存器中可以提高程序的运行效率。

组成部分:
register:这是一个存储类说明符,用于建议编译器将变量存储在寄存器中。
int:这是一个数据类型,表示整数。
使用场景:
在早期的 C 和 C++ 程序中,程序员可能会使用 register int 来声明那些在循环或频繁操作中使用,且对性能有较高要求的变量。例如:

register int i;
for (i = 0; i < 1000; i++) {
// 循环体
}
注意事项:
编译器的自由裁量:尽管程序员可以使用 register 来建议编译器将变量存储在寄存器中,但编译器有权忽略这个建议,因为编译器会根据实际情况决定如何最优化代码。

现代编译器的优化:随着编译器技术的发展,现代编译器已经非常智能,能够自动决定哪些变量应该存储在寄存器中。因此,显式使用 register 的需求已经大大降低。

C++17 弃用:在 C++17 标准中,register 已经被标记为弃用,这意味着在未来的 C++ 版本中,这个关键字可能会被完全移除。

现代硬件的影响:现代 CPU 拥有更多的寄存器,以及更复杂的缓存系统,这使得编译器的自动优化更加有效,减少了程序员手动优化的必要性。

总的来说,register int 是一个遗留自早期编程实践的概念,它反映了程序员试图通过手动优化来提高程序性能的努力。然而,在现代编程实践中,这种优化方式已经不再常见,编译器的自动优化通常更加有效。

register int即RI。
在 C++ 代码中,RI 是一个宏定义(macro),用于声明一个 register int 类型的变量。register 是 C++ 中的一个关键字,用于建议编译器将变量存储在寄存器中而不是内存中。这样做的目的是为了提高访问变量的速度,因为寄存器的访问速度通常比内存快得多。

然而,需要注意的是,在现代编译器中,register 关键字的影响已经非常有限,因为编译器通常能够自动做出最优化的决策。此外,从 C++11 开始,register 关键字已经不再被推荐使用,并且在 C++17 中被标记为弃用。

在提供的代码中,RI 被定义为 register int,这通常用于声明一个局部变量,例如:

RI i; // 使用 RI 宏定义声明一个 register int 类型的变量 i

这行代码的作用等同于直接声明一个 register int 类型的变量 i。在某些情况下,使用 register 关键字可能会对编译器的优化产生一定的影响,但这种影响通常很小,而且在现代编程实践中,通常不再使用 register 关键字。

四.getline

getline 是 C++ 标准库中的一个函数,用于从输入流中读取一行字符串。这个函数可以处理空格和换行符,与 cin >> 不同的是,getline 会读取并包含字符串中的空格,直到遇到换行符。

函数的基本用法如下:

getline(istream& is, string& str);
  • is 是输入流的引用,可以是 cin、文件流(如 ifstream)或任何其他输入流对象。
  • str 是一个字符串变量的引用,用于存储从输入流中读取的行。

函数从输入流中读取字符,直到遇到换行符('\n')为止。换行符不会被存储在字符串中,但会在字符串末尾添加一个空字符('\0')以形成一个正确的字符串终止符。

示例用法:

  1. cin 读取一行:
#include <iostream>
#include <string>

int main() {
    std::string line;
    std::cout << "请输入一行文本:" << std::endl;
    std::getline(std::cin, line);
    std::cout << "你输入的行是:" << line << std::endl;
    return 0;
}
  1. 从文件流中读取一行:
#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::ifstream file("example.txt");
    std::string line;
    if (file.is_open()) {
        while (std::getline(file, line)) {
            std::cout << line << std::endl;
        }
        file.close();
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    return 0;
}

注意事项:

  • 如果输入流已经处于错误状态(如文件未打开),getline 将不会读取任何内容,并返回 false。
  • getline 可以正确处理包含空格的行,这与 cin >> 形成对比,后者会在遇到空格时停止读取。
  • 如果需要从 cin 读取多个值,并且希望包括空格,可以使用 getline 读取整行,然后使用 std::istringstream 来分割该行。

五.istringstream的用法

istringstream iss1(line); 这行代码在C++中创建了一个名为 iss1istringstream 对象。istringstream 是定义在 <sstream> 头文件中的一个类,它是标准库中的一个字符串流(string stream)类,用于将字符串作为流来处理。

这里的 istringstream 被用来从字符串中读取数据,就像从一个文件或标准输入流中读取数据一样。你可以使用流提取操作符 >>istringstream 对象中提取数据,这与从 cin 或文件流中提取数据的方式相同。

具体来说,istringstream iss1(line); 这行代码做了以下几件事:

  1. 创建了一个 istringstream 类型的对象 iss1
  2. line 字符串作为参数传递给 iss1 的构造函数,这样 iss1 就包含了 line 字符串的内容。
  3. 现在,iss1 可以像处理标准输入流 cin 一样被用来读取数据。例如,你可以使用 iss1 >> num; 来从 iss1 中读取整数到变量 num

这种方式常用于需要从单个字符串中多次读取多个数据值的场景。通过将字符串转换为流,你可以使用标准的输入流操作符来逐个提取字符串中的值。

标签:数据结构,函数,int,register,C++,编译器,inline,20241024,大二
From: https://www.cnblogs.com/landboat/p/18499611

相关文章

  • 数据结构与算法——双链表的实现
    上次学习了单链表,这次来学习双链表。二者之间的区别是,单链表中的每个结点只存有后继结点的地址,而双链表中则存了两个地址,一个是前驱结点的地址,一个是后继结点的地址。结构体structListNode{ intelement;//数据域 structListNode*next; ......
  • 数据结构懒标记时间戳差异问题
    对于数据结构打lazytag后节点时空不统一问题的解决可以看看之前写的一篇文章线段树初步理解,里头初步介绍了懒标记的作用与使用懒标记所带来的时空不统一的问题。实际上是可以将懒标记拓展到其他数据结构上的。就以经典的毛毛虫链剖分举例子,就是现在我要给树上的与给定......
  • 【C++篇】栈的层叠与队列的流动:在 STL 的韵律中探寻数据结构的优雅之舞
    文章目录C++栈与队列详解:基础与进阶应用前言第一章:栈的介绍与使用1.1栈的介绍1.2栈的使用1.2.1最小栈1.2.2示例与输出1.3栈的模拟实现第二章:队列的介绍与使用2.1队列的介绍2.2队列的使用2.2.1示例与输出2.3队列的模拟实现2.3.1示例与输出第三章:优先队......
  • 第十三章_数据结构与集合源码二
    目录8.Map接口分析8.1哈希表的物理结构8.2HashMap中数据添加过程8.2.1JDK7中过程分析8.2.2JDK8中过程分析8.3HashMap源码剖析8.3.1JDK1.7.0_07中源码1、Entry2、属性3、构造器4、put()方法8.3.2JDK1.8.0_271中源码1、Node2、属性3、构造器4、put()方法......
  • 【数据结构】-数组
    数组特点:数组的地址连续,可以通过下标获取数据。1.数组扩容步骤:$1.创建一个比原来数组更长的新数组$2.让原来数组当中的数据依次复制到新数组当中$3.让arr指向新数组,原数组空间释放  2.数组插入2.1最后位置插入$1.判断数组当中有没有位置,用size记录当......
  • 新高一暑假第一期集训恢复性训练【数据结构-晚测】(并查集)(补)
    新高一暑假第一期集训恢复性训练【数据结构-晚测】(并查集)(补)[CF1290C]PrefixEnlightment带权扩展域并查集。任意三个子集的交集为空集,显然,一个点最多只能在两个集合中出现,这样所有集合的大小之和是\(\Theta(n)\)的。一个在两个集合中出现的点ii相当于连接了\(2\)个集合......
  • [数据结构] 删除单链表中最小值结点(C语言版本)
    如果对单链表基本操作或概念不理解的可以跳转:单链表的基本操作(C语言版)-CSDN博客https://blog.csdn.net/m0_74181956/article/details/143082621?spm=1001.2014.3001.5501算法思想:如图所示:定义指针p为L的第一个结点,pre为L的头结点,min为记录每次遍历的最小值结点,minpre为记......
  • 数据结构C语言版_队列笔记||已测试所有代码均可运行
    队列源文件使用markdown编写,CSDN文章发布好像有部分语法改变。每一部分我都有加一个返回标题好像不能使用了。但是CSDN自带一个目录总结,你们无视掉我写的目录直接用CSDN的吧。总结笔记不易,如果有帮助到你希望点个赞。所有代码均已在VScode中运行过,部分代码块因为格式原因......
  • 【数据结构与算法】之龟兔赛跑算法
    目录一、龟兔赛跑算法1.1阶段11.2阶段21.3为什么呢?二、判断是否有环2.1问题描述2.2示例2.3 代码实现三、找到环入口3.1问题描述3.2示例3.3代码实现总结本文主要介绍以环形链表相关的算法,主要采用Java语言实现,这类算法又称Floyd'sTortoiseandHare......
  • 数据结构-----------栈和队列后续
    1队列1.1概念与结构概念:只允许在一端进行插入数据操作,在另一端进行删除元素特殊的线性表,队列具有先进先出的性质入队列:进行插入操作的的一端叫做队尾出队列:进行删除操作的一端叫做队头下面我们来看一下队列的实现队列其实跟单链表是差不多的只不过队列只允许在队尾插入数......