技术标签: C++ 面试题 面试 C++ Qt 其它 基础面试题 Qt面试
又到了金三银四的季节,每年这个时候都是跳槽的高峰期,在整理电脑资料的过程中发现一些之前记录的面试过程中最常提到的C++和Qt相关问题,其实都是些很基础的知识点,但是在面试过程中出镜率非常高。总结如下,仅供参考。
废话不多说,直接上题。
1.互斥锁 (std::mutex):通过锁来保证同一时刻只有一个线程访问共享资源,其他线程必须等待锁的释放才能访问。
2.信号量 (std::semaphore):可以控制并发访问共享资源线程的数目。
3.条件变量 (std::condition_variable):用于多线程编程中发生线程等待的情况,可以按照一定的顺序唤醒线程。
4.原子操作 (std::atomic):基于硬件提供的CAS (compare-and-swap) 操作,可以让变量的赋值操作等价于一个原子操作,支持多线程并发。
5.读写锁 (std::shared_mutex):用于多线程读写共享资源时,读取共享资源的线程是安全的,但写入共享资源的线程需要独占资源,其余线程需要等待写操作完成。
6.屏障 (std::barrier):用于多线程编程中让多个线程进入某个点时再继续执行,可以帮助优化性能,提高并行度。
7.原子操作库 (std::atomic_library):在std::atomic的基础上提供了更多的原子操作,比如_fetch_add,_fetch_sub等等。
- 共享内存:通过在进程间共享内存来实现线程间的通信。需要设计好共享内存区域的数据结构,保证线程操作时不会发生竞态条件。
- 消息队列:通过发送和接收不同类型的消息,在线程之间传递信息。可以使用系统提供的消息队列如POSIX消息队列、ZeroMQ,或自己在共享内存中实现一个消息队列。
- 管道:管道是Linux系统中的一种通信方式,可以用于进程间的通信,也可以用于线程间通信。
- 信号量:可以用于不同线程之间的同步和互斥。可以使用系统提供的信号量如POSIX信号量,也可以使用C++11库中提供的信号量。
- 条件变量:往往用于某个线程等待另一个线程完成某些操作,然后通知正在等待的线程。
- 互斥锁:主要用于解决多个线程访问共享数据时可能导致的竞态条件。线程通过获取锁来申明对共享资源的独占,然后再进行访问。
在使用这些线程间通信机制时,需要根据实际场景选择最适合的机制以获得最佳的性能。
- 阻塞IO模型(Blocking IO Model)
- 非阻塞IO模型(Non-Blocking IO Model)
- 多路复用IO模型(Multiplexing IO Model)
- 信号驱动IO模型(Signal Driven IO Model)
- 异步IO模型(Asynchronous IO Model)
其中,阻塞IO模型是默认的模型,它的效率不高,但代码实现简单;非阻塞IO模型通过不断地轮询检查IO事件的状态,实现了一定程度的并发,但也存在效率较低的问题;多路复用IO模型(如epoll或select)使用单个进程处理多个IO连接,大大降低了系统开销,提高了并发性能;信号驱动IO模型类似于多路复用IO模型,但它使用信号来通知程序有事件发生;异步IO模型(如aio或libuv)则是将IO请求提交给操作系统,等操作系统完成后再通知程序,效率最高,但使用起来复杂一些。
虚函数是C++中的一种实现多态性的机制,它能够在运行时动态地确定调用哪个函数,而不是在编译时就确定。虚函数通过在成员函数前加上virtual关键字来声明。
在C++中,每个具有至少一个虚函数的类都有一个虚函数表(也叫虚表)来维护函数指针。当类被实例化时,每个对象会包含一个指向该类的虚函数表的指针。当调用虚函数时,根据对象指针上的虚函数表指针查找对应的函数指针,并通过该函数指针调用虚函数的实现。
虚函数表是一个数组,其中每个元素是一个函数指针,对应一个虚函数的实现。虚函数表指针指向虚函数表的首地址。虚函数的索引就是它在虚函数表中的索引。函数的实现是通过函数指针调用的。
对于菱形继承结构,一个子类继承了多个父类,每个父类中都可能有虚函数,会导致继承链上存在多个虚函数表。为了避免出现重复的虚函数表,C++采用了虚函数表指针的共享方式。即,通过虚函数表指针共享父类的虚函数表,从而避免了数据的重复存储。C++编译器对每个子类都会在虚函数表中分配一些空间,用于存储子类自己新增的虚函数,将原来父类的虚函数表中的函数指针拷贝到子类的虚函数表中。当调用父类的虚函数时,会先通过虚函数表指针查找到父类虚函数表,然后根据虚函数在虚函数表中的索引找到对应的函数指针,最后调用函数实现。
C++ 内存分区:栈、堆、全局/静态存储区、常量存储区、代码区。
1.栈:存放函数的局部变量、函数参数、返回地址等,由编译器自动分配和释放。
2.堆:动态申请的内存空间,就是由 malloc 分配的内存块,由程序员控制它的分配和释放,如果程序执行结束还没有释放,操作系统会自动回收。
3.全局区/静态存储区(.bss 段和 .data 段):存放全局变量和静态变量,程序运行结束操作系统自动释放,在 C 语言中,未初始化的放在 .bss 段中,初始化的放在 .data 段中,C++ 中不再区分了。
4.常量存储区(.data 段):存放的是常量,不允许修改,程序运行结束自动释放。
5.代码区(.text 段):存放代码,不允许修改,但可以执行。编译后的二进制文件存放在这里。
malloc和free是C语言标准库中用于动态分配和释放内存的函数,new和delete是C++语言中用于动态分配和释放内存的运算符,它们的作用相同,但是使用方式和语法不同。
主要有以下几个区别:
- malloc和free是函数,需要#include <stdlib.h>库文件;new和delete是运算符,不需要任何库文件。
- malloc只负责给定一个大小,而并不负责构造对象;new在分配完内存后还会调用构造函数。
- free只负责释放内存,而不会调用对象的析构函数;delete在释放内存前,还会先调用对象的析构函数。
不能混用的原因是,malloc和free的内部机制与new和delete不同,它们使用的底层内存分配算法不同。在使用malloc分配内存时,返回的是一块原始的内存空间,这块空间中并没有对象,需要手动构造对象。而使用new运算符时,它会调用类的构造函数构造对象,将对象的构造和内存的分配联系在了一起。如果混用的话,就会导致对象的构造和析构不匹配,导致内存泄漏或者程序崩溃等问题。另外,new分配的内存必须使用delete释放,malloc分配的内存必须使用free释放,否则也会出现内存泄漏等问题。
可参考这里
13.红黑树实现原理
14.查找算法有哪些
常见的查找算法有以下几种:
线性查找(顺序查找) 时间复杂度:O(n) 空间复杂度:O(1)
二分查找(折半查找) 时间复杂度:O(logn) 空间复杂度:O(1)
插值查找 时间复杂度:O(log(logn)) 空间复杂度:O(1)
斐波那契查找 时间复杂度:O(logn) 空间复杂度:O(1)
哈希查找 时间复杂度:O(1) (平均情况) 空间复杂度:O(n)
15.排序算法有哪些
常见的排序算法有以下几种:
冒泡排序 时间复杂度:O(n^2) 空间复杂度:O(1)
插入排序 时间复杂度:O(n^2) 空间复杂度:O(1)
选择排序 时间复杂度:O(n^2) 空间复杂度:O(1)
快速排序 时间复杂度:O(nlogn) 空间复杂度:O(logn) (递归栈的空间)
归并排序 时间复杂度:O(nlogn) 空间复杂度:O(n)
堆排序 时间复杂度:O(nlogn) 空间复杂度:O(1)
以上算法的时间复杂度和空间复杂度都是根据具体实现方式以及数据规模而不同。需要根据具体使用场景进行选择和优化。其中,快速排序和归并排序是常用的高效排序算法,堆排序适合在数据集合较大时使用,插入排序、选择排序和冒泡排序适合在数据量较小或是数据已经基本有序时使用。
快速排序(QuickSort)是一种基于比较的排序算法,采用分治策略来对一个数组进行排序。其基本思想是:首先选取一个枢纽元素(pivot element),将数组划分为两个子序列,其中一个子序列中的所有元素都小于枢纽元素,另一个子序列中的所有元素都大于枢纽元素;然后对这两个子序列分别递归地进行快速排序,直到整个序列有序为止。
快速排序的基本步骤如下:
首先选取一个枢纽元素(pivot element),一般可以随机选择待排序数组中的一个元素。
将待排序数组划分为两个子序列,使得一个子序列中的所有元素都小于枢纽元素,另一个子序列中的所有元素都大于等于枢纽元素。这个过程称为划分(Partition)操作。
对左右两个子序列分别递归地执行以上两步,直到子序列长度为1时排序结束。
快速排序中的划分操作,一般有以下几种实现方式:
挖坑填数法:先将枢纽元素存入一个变量中,然后将待排序数组中第一个元素作为枢纽元素,从后往前找到第一个小于枢纽元素的元素,将其移动到前面的空位上,然后从前往后找到第一个大于枢纽元素的元素,将其移动到后面的空位上,重复此过程,直到两个指针相遇时,将枢纽元素放入最终的空位中。
左右指针法:定义两个指针分别指向待排序区间的左右两端,然后从右往左找到第一个小于枢纽元素的元素,从左往右找到第一个大于等于枢纽元素的元素,交换它们的位置,重复此过程,直到左右指针相遇,然后将枢纽元素放入最终的位置。
快速排序的时间复杂度为 O(nlogn)(最坏的情况是 O(n^2)),空间复杂度为 O(logn)(最坏的情况是 O(n))。由于快速排序采用原地排序方式,不需要额外的内存空间,同时由于采用了分治策略,使得快速排序的排序速度很快,是一种常用的排序算法。
- 指针有自己的一块空间,而引用只是一个别名
- 指针的大小是4,引用则是被引用对象的大小
- 指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象的引用
- 作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对应用的修改都会改变引用所指向的对象
- 可以有const指针,但没有const引用
- 指针在使用中可以指向其他对象,但是引用只能是一个对象的引用,不能被改变
- 指针可以有多级指针(**p),而引用只有一级
- 指针和引用使用++运算符的意义不一样
- 如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏。
1 . (点运算符)通常用于去对象的成员,但是->(箭头运算符),是可以重载的
2 ::(域运算符)即类名+域运算符,取成员,不可以重载
3 .* (点星运算符,)不可以重载,成员指针运算符".*,即成员是指针类型
4 ?: (条件运算符)不可以重载
5 sizeof 不可以重载
线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。
线程安全问题大多是由全局变量及静态变量引起的,局部变量逃逸也可能导致线程安全问题。
reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。
resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。
再者,两个函数的形式是有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小,第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。
1.申请方式:栈是系统自动分配,堆是程序员主动申请。
2.申请后系统响应:分配栈空间,如果剩余空间大于申请空间则分配成功,否则分配失败栈溢出;申请堆空间,堆在内存中呈现的方式类似于链表(记录空闲地址空间的链表),在链表上寻找第一个大于申请空间的节点分配给程序,将该节点从链表中删除,大多数系统中该块空间的首地址存放的是本次分配空间的大小,便于释放,将该块空间上的剩余空间再次连接在空闲链表上。
3.栈在内存中是连续的一块空间(向低地址扩展)最大容量是系统预定好的,堆在内存中的空间(向高地址扩展)是不连续的。
4.申请效率:栈是有系统自动分配,申请效率高,但程序员无法控制;堆是由程序员主动申请,效率低,使用起来方便但是容易产生碎片。
5.存放的内容:栈中存放的是局部变量,函数的参数;堆中存放的内容由程序员控制。
二叉搜索树,左子树的所有节点都小于当前节点,右子树的所有节点都大于当前节点,并且每棵子树都具有上述特点
- 创建对象时,需要确定对象的类型,而虚函数是在运行时动态确定其类型的。在构造一个对象时,由于对象还未创建成功,编译器无法知道对象的实际类型;
- 虚函数的调用需要通过vptr虚函数表指针,而该指针是存放在对象的内存空间中的,若构造函数声明为虚函数,那么由于对象尚未创建,还没有内存空间,也就没有对应虚函数表来调用虚构造函数了;
- 虚函数的作用在于通过父类的指针或者引用,在调用它的时候能够通过动态链编调用子类重写的虚成员函数。而构造函数是在创建对象时是系统自动调用的,不可能通过父类或者引用去调用,因此就规定构造函数不能是虚函数。
信号与槽的具体流程。
- moc查找头文件中的signals,slots,标记出信号和槽。
- 将信号槽信息存储到类静态变量staticMetaObject中,并且按声明顺序进行存放,建立索引。
- 当发现有connect连接时,将信号槽的索引信息放到一个map中,彼此配对。
- 当调用emit时,调用信号函数,并且传递发送信号的对象指针,元对象指针,信号索引,参数列表到active函数
- 通过active函数找到在map中找到所有与信号对应的槽索引
- 根据槽索引找到槽函数,执行槽函数。
Qt的消息循环是指Qt框架内部的一个循环,主要用于处理各种事件(例如用户输入、网络数据接收等)和信号槽等异步操作。
在Qt中,消息循环主要由QCoreApplication和QEventLoop两个类来实现。QCoreApplication是Qt框架的核心类之一,它初始化了整个应用程序并提供了主事件循环。QEventLoop则负责在事件队列中循环直到队列中没有事件,处理事件时它会阻塞当前线程,直到有事件到来或者定时器到期等情况。
消息循环的原理如下:
1.Qt程序启动后,QCoreApplication会创建一个全局QEventLoop对象。
2.当用户有输入事件(如鼠标、键盘等)或者其他事件(如定时器超时、网络数据到达等)时,这些事件会被转换成Qt框架内部的事件对象,并通过QApplication::postEvent()或QCoreApplication::sendEvent()等函数添加到事件队列中。
3.QCoreApplication::exec()函数会启动事件循环,并保持应用程序处于运行状态。在循环的过程中,QEventLoop会等待事件的到来,当有事件时进行处理。如果事件队列为空,QEventLoop会一直等待,并阻塞当前线程。
4.当事件处理完成后,消息循环会继续等待下一个事件,直到exit()函数被调用或者手动中断循环。
总体来说,Qt的消息循环机制非常灵活,可以简化异步操作的实现,并且方便对事件进行管理和处理。
QML 和 C++ 的交互方式主要分为以下两种:
- 属性绑定:QML 提供了属性绑定的机制,可以将 QML 中的属性与 C++ 中的属性相互绑定,当 C++ 中的属性发生变化时,QML 中的属性也会相应发生变化。具体的实现方式是使用 C++ 暴露给 QML 的对象作为属性源,然后在 QML 中使用属性绑定将其绑定到对应的属性上。
- 接口调用:QML 也可以通过 C++ 提供的接口调用 C++ 中的函数。通过 C++ 暴露给 QML 的对象的方法,在 QML 中可以使用 QML 的语法直接调用对应的函数。
异步,可以用QEventLoop实现同步
Qt 支持这些信号槽连接类型:
1、Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。
2、Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数和信号发送者在同一线程。效果看上去就像是直接在信号发送位置调用了槽函数,效果上看起来像函数调用,同步执行。
emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕
3、Qt::QueuedConnection:信号发出后,信号会暂时被放到一个消息队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。
emit语句后面的代码将在与信号关联的所有槽函数执行完毕后才被执行。
4、Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。而且接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
5、Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。
可以通过将附加参数传递给connect()来指定连接类型。请注意,如果事件循环在接收者的线程中运行,则在发送者和接收者位于不同线程中时使用直接连接是不安全的,原因与调用位于另一个线程中的对象上的任何函数是不安全的原因相同。
QObject::connect () 本身是线程安全的。
元对象系统提供了三个功能:信号槽,运行时类型识别(RTTI),动态属性系统。但是这三个概念不是严格意义上的并列关系,我更倾向于这么记忆:元对象系统实现了动态属性系统,然后在动态属性系统的基础上,实现了信号槽、RTTI、QVariant动态类型、插件系统、跨语言调用(QML调用C++)
具体参考
Qt跨平台的优点:
1.能够快速开发跨平台的应用程序,节省了开发时间和开发成本。
2.具有丰富的UI组件库,支持多种操作系统,包括Windows、macOS、iOS、Android、Linux等,便于开发者开发。
3.Qt提供了完整的编程框架和工具,包括Qt Creator等,可以方便地进行跨平台开发和调试。
4.Qt的API设计非常简单和易于使用,使用Qt的开发者可以轻松地为多种平台创建相同的应用程序,而无需了解每个平台的细节。
5.Qt拥有强大的消息传递机制,支持信号和槽机制和事件驱动式的编程模型,使得程序的性能更加优秀。
Qt跨平台的缺点:
Qt的跨平台性可能不如直接使用底层API的本地应用程序,可能会使得某些特定平台的应用程序不够优化。
Qt有一个相对较大的代码库,并且在开发跨平台应用程序时,可能需要包含额外的库文件和组件,增加了应用程序的大小。
Qt在不同平台之间的UI组件可能有所不同,必须进行针对性的开发,增加了开发的复杂性。
Qt可能存在性能问题,在一些特殊的应用领域可能不太适用。
综上所述,Qt作为一种跨平台解决方案,优缺点相较于其他技术都是相对的,需要根据具体的应用场景来确定使用它的可行性。但总的来说,Qt作为一个成熟和广泛使用的开发工具,它的跨平台性仍然是其最突出的优点之一。
Windows消息传递机制是Windows操作系统中用于实现不同应用程序间或同一应用程序不同线程间互相通信的机制。其基本原理是将消息发送者的消息封装成一个窗口消息(Window Message)或系统消息(System Message),然后将消息发送到一个特定的窗口句柄或线程句柄,接收消息的程序或线程则通过消息循环或消息回调函数来接收和处理消息。
在Windows操作系统中,窗口句柄(Window Handle)是消息传递机制的重要概念。每一个窗口都对应一个唯一的窗口句柄,用于在系统中唯一标识一个窗口。发送消息的程序或线程通过窗口句柄来定位消息接收程序或线程。Windows操作系统中有大量的API供程序员使用,如SendMessage和PostMessage等函数都是用于发送消息到指定的窗口句柄。
另外,Windows操作系统中还有一种特殊的窗口,即控制台窗口(Console Window)。控制台窗口不是普通窗口,而是由CMD.EXE创建的,主要用于提供文本模式下的用户界面。SendMessage和PostMessage函数不能直接发送消息到控制台窗口,需要使用其他API来实现,如WriteConsoleInput和WriteConsoleOutput等函数。
消息队列(Message Queue,简称MQ)是一种应用程序解耦和异步通信的技术。它是一种跨进程或跨网络的通信方式,用于在一个系统中不同的应用程序之间传递数据和消息。
消息队列采用一种生产者/消费者模型,在这个模型中,消息的创建者称为生产者,消息的接收者称为消费者。生产者将消息发送到队列中,而消费者则从队列中取出消息并处理它们。这种模型能够有效地解耦和应用程序,使得它们可以独立地进行开发和部署,从而提高应用程序的可伸缩性、可靠性和可维护性。
可参考
一个进程可以创建多个消息队列。在大多数操作系统中,一个进程可以创建多个消息队列,并且每个队列都可以设置不同的属性,如队列大小和消息优先级等。一个进程可以将多个消息发送到不同的队列中,或者从不同的队列中接收消息。这种灵活性可以使得应用程序更容易进行进程间通信和协作。
sendMessage和postMessage是两个不同的概念。
sendMessage通常指的是在同一进程中的线程之间传递消息,例如在Windows操作系统中使用SendMessage函数,在Android操作系统中使用Handler.sendMessage方法。sendMessage的调用是同步的,即特定的线程在发送完消息后会等待接收线程处理完消息后再继续执行。
postMessage通常指在Web Worker中向主线程或从主线程向Web Worker发送消息。postMessage的调用是异步的,即发送消息后就立刻返回,不会阻止发送消息的线程继续执行。接收线程处理完消息后会通过回调函数通知发送线程。
总的来说,sendMessage和postMessage都是用于在不同的执行上下文中传递消息,不同的是它们在同步异步处理上的区别。
TCP协议在建立连接时需要进行三次握手(SYN, SYN-ACK, ACK)和四次挥手(FIN, ACK, FIN, ACK)。
TCP三次握手(Established Connection):
TCP四次挥手(Terminate Connection):
TCP三次握手和四次挥手保证了数据传输的可靠性和完整性。
客户端进入TIME_WAIT状态是为了确保已经发送的最后一个ACK包被服务器端正确接收,以确保这条TCP连接的数据传输的可靠性和完整性。具体原因如下:
可靠关闭: 客户端向服务器发送FIN包后,服务器端收到FIN包后会发送ACK包,确保客户端的FIN包被正确接收。此时客户端进入FIN_WAIT2状态,等待服务器端发送FIN包。如果服务器端没有正确接收这个ACK包,就可能会认为客户端并没有接收到服务器端发送的FIN包,导致不必要的超时或重发,因此客户端需要等待一段时间,确保服务器端已经接收到了ACK包,从而保证TCP连接的可靠关闭。
避免重复连接:客户端在TIME_WAIT状态下会等待一段时间,确保服务器端发送的FIN包能够正确到达,从而防止该连接的后续报文段被其他连接错误地使用。
总之,TIME_WAIT状态的作用是确保TCP连接的可靠关闭,保证这条连接的数据传输的可靠性和完整性。此时客户端会等待一段时间,以确保所有相关的数据都已被正确传输和接收。
网络传输协议制定需要考虑多方面因素,例如传输的数据类型、安全性、效率、可扩展性、兼容性等。一般而言,网络传输协议要包含以下几个方面的设计:
- 1.传输协议首部:传输协议首部是协议定义中最重要的部分之一,它包含了协议版本、控制位、源地址、目的地址等信息,能够有效地管理传输中的数据。
- 2.传输数据:传输协议中要定义数据传输方式,例如TCP协议中通过三次握手建立连接,传输数据时采用流式传输方式,保证数据的可靠性;而UDP协议则通过数据报方式传输数据,只提供基础的错误检查。
- 3.传输流程控制:传输协议中还需对数据的流程进行控制,如TCP协议通过滑动窗口方法来控制数据的发送和接收,保证数据流量的平滑。
- 4.错误处理及恢复:在数据传输过程中,可能会出现各种错误,为了保证数据的正确传输,协议中必须定义相应的错误处理机制,例如TCP协议中提供有序可靠的重传机制来避免数据丢失。
除此之外,传输协议的设计还应该考虑安全性、效率、拓展性、兼容性等问题,设计出高效、稳定、安全的传输协议。
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {
}
};
ListNode* createList(int n) {
ListNode* dummy = new ListNode(-1);
ListNode* curr = dummy;
for(int i = 1; i <= n; ++i) {
int val;
cin >> val;
curr->next = new ListNode(val);
curr = curr->next;
}
return dummy->next;
}
int main() {
ListNode* head = createList(10);
while(head) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
return 0;
}
std::vector<int> v = {
1,3,5,6,3,4,7,3};
for(auto it = v.begin(); it != v.end();){
cout << "*it=" << *it << endl;
if(*it == 3){
it = v.erase(it);
}
else{
it++;
}
}
在之前的博客中也总结过一些关于C/C++ 的基础知识点,可供参考:
C/C++基础知识点(一)
C/C++基础知识点(二)
C/C++基础知识点(三)
C/C++基础知识点(四)
上面这些是之前面试中遇到过的一些常见问题,另外,还整理了一份更详细的复习资料,也是关于C++基础知识以及相关经典面试题,还有一份数据结构和算法的面试手册,非常详细,有需要的可以下载学习。
以上资料附带详细答案。
下载地址
文章浏览阅读202次。it's common to see something like this in code, hopefully only during development://XXX: not in production!String password = "hello"; // getActualPassword(...);...catch(Exception e) { /* TODO: Auto-ge..._蚂蚁怎么修改网站源代码
文章浏览阅读7.7k次,点赞6次,收藏16次。PMP习题_一个组织在历史上一直使用预测性方法
文章浏览阅读2w次,点赞19次,收藏43次。前叙本来想要研究mint-ui组件库的Lazy load组件,没想到翻看它的源码,发现它完全引用的vue-lazyload项目,直接引用,没有丝毫修改。 因此转而研究vue-lazyload,代码并不多,几百行吧,有兴趣的可以读一下。简单接入示例html代码:
文章浏览阅读268次。October 25, 2019 Brian McClainThis post was co-written with Ben Wilcock, Product and Technical Marketing Manager for Spring at Pivotal.???? A file has been uploaded! ???????? A new user was registered! ???????? ..._please use 'spring.cloud.function.definition' property to explicitly define
文章浏览阅读740次,点赞21次,收藏20次。Acunetix Web Vulnerability Scanner(AWVS)可以扫描任何通过Web浏览器访问和遵循HTTP/HTTPS规则的Web站点。适用于任何中小型和大型企业的内联网、外延网和面向客户、雇员、厂商和其它人员的Web网站。AWVS可以通过检查SQL注入攻击漏洞、XSS跨站脚本攻击漏洞等漏洞来审核Web应用程序的安全性。主菜单功能介绍:主菜单共有5个模块,分别为Dashboard、Targets、Vulnerabilities、Scans和Reports。_awvs csdn
文章浏览阅读238次。这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是毕设分享 基于STM32的智能水产养殖系统(源码+硬件+论文)学长这里给一个题目综合评分(每项满分5分)难度系数:3分工作量:3分创新点:4分包含内容。_毕业设计水产养殖
文章浏览阅读136次。前置条件kafka 集群软件信息网盘下载地址链接:https://pan.baidu.com/s/1b5DjLQBmbz_8Nh7DyLj2BQ提取码:gin1install当前安装演示版本apache-flume-1.9.0-bin.tar.gzinstall# 解压tar -zxf apache-flume-1.9.0-bin.tar.gz -C /home/kafka/# 查看cd /home/kafka/apache-flume-1.9.0-bin/l
文章浏览阅读206次。IDC预测,到2025年全球数据规模将达到175 ZB,这为人工智能模型训练提供了海量数据资源,全球AI产业迅速发展为创业者们带来了巨大的机遇,但也提出了全新的挑战。新的市场、高效的工具和智能的资源,开辟了创新的领域和商业模式,也激发了创业者们的创造力和想象力。如何找对前进的方向,请听听来自不同热门赛道创业者与亚马逊云科技的故事。潞晨科技初创即高峰,跻身当下最火热的开源AI大模型赛道前列,GitHub Star摘星两万颗潞晨科技是一家致力于“解放AI生产力”的全球性公司,其核心产品_创业者之日
文章浏览阅读3.9k次。串是由零个或多个字符组成的有限序列,在计算机科学中是一种重要的数据类型。字符可以是字母、数字、符号等,对应于计算机中的编码。串可以用来表示文本、图像、音频等数据char* data;int max;int len;}sstring;/*初始化串*//*字符拷贝*//*模式匹配*///串比较//串长//串的联接。_字符串
文章浏览阅读1.1k次。关于APNIC (Asia-Pacific Network Information Centre)是现在在世界中操作的五个地区的英特网登记处之一,分配B类IP地址的国际组织。它提供全球性的支持互联网操作的分派和注册服务。这是成员包括网络服务提供商、全国互联网登记, 和相似的组织的一个非营利, 基于会员资格的组织。APNIC 就是"亚太地区互联网信息中心",负责分配亚洲太平洋区域的网站IP地址,包含_apnic是什么意思
文章浏览阅读87次。进制转换Time Limit:1000MS Memory Limit:30000KBTotal Submit:2041 Accepted:765Description 输入一个十进制数N,将它转换成R进制数输出。Input 输入一个正整数T。表示测试数据的组数。每个测试实例包含两个整数N(32位整数)和R(2Output 为每个测试实
文章浏览阅读604次。http://blog.163.com/china_uv/blog/static/1171372672014111681232340/本文翻译自:stackoverflow有人在stackoverflow上问了一个问题:如何在UITableViewCell中使用Autolayout来实现Cell的内容和子视图自动计算行高,并且能够保持平滑滚动的?_ios cell布局完成会调用什么方法?