C++面试题目

C++和C的区别

总览

  1. C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。
  2. C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。 所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”。

设计思想上:

  • C++是面向对象的语言,而C是面向过程的结构化编程语言

语法上:

  • C++具有封装、继承和多态三种特性。封装体现在类,继承体现在类,多态体现在虚函数、类、友元
  • C++相比C,增加多许多类型安全的功能,比如强制类型转换(四个),const、private、智能指针、引用
  • C++支持范式编程,比如模板类、函数模板等,STL

C++对C的增强

  • (1) 类型检查更为严格:C++ 通过使用基类指针或引用来代替 void* 的使用,避免了这个问题(其实也是体现了类继承的多态性)
  • (2) 增加了面向对象的机制:C++允许结构体中封装函数,而在其他的地方直接调用这个函数。这个封装好的可直接调用的模块有个新名词——对象;并且也把结构体换一个名字——类。这就是面向对象的思想。在构建对象的时候,把对象的一些操作全部定义好并且给出接口的方式,对于外部使用者而言,可以不需要知道函数的处理过程,只需要知道调用方式、传递参数、返回值、处理结果。
  • (3)增加了泛型编程的机制(Template):不同的类型采用相同的方式来操作,模版技术具有比类、函数更高的抽象水平,因为模版能够生成出(实例化)类和函数。可以用来: 1,替换类型(最常用的 vector<T>);2,判定类型(is_integral<T>)和类型间的关系(is_convertible<From, To>) ;3,控制模版函数的实例化(SFINAE ---> enable_if<bool, T>)
  • (4)增加了异常处理:C++ 提供了一系列标准的异常,定义在 <exception> 中,可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的,如下所示:

  • (5)增加了运算符重载:C++ 可以实现函数重载,条件是:函数名必须相同,返回值类型也必须相同,但参数的个数、类型或顺序至少有其一不同。而重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。大多数的重载运算符可被定义为普通的非成员函数(func(a, b) 形式调用)或者被定义为类成员函数(a.func(b) 形式调用)
  • (6)增加了标准模板库(STL)STL 的数据结构和内部实现
  • (7)C和C++动态管理内存的方法不一样:C是使用malloc、free函数,而C++不仅有malloc/free,还有new/delete关键字。那malloc/free和new/delete差别? malloc/free和new/delete差别: ①、malloc/free是C和C++语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。 ②、由于malloc/free是库函数不是运算符,不在编译器范围之内,不能够把执行构造函数和析构函数的任务强加入malloc/free。因此C++需要一个能完成动态内存分配和初始化工作的运算符new,一个能完成清理与释放内存工作的运算符delete。 ③、new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void指针。 ④、malloc是从堆上开辟空间,而new是从自由存储区开辟(自由存储区是从C++抽象出来的概念,不仅可以是堆,还可以是静态存储区)。 ⑤、malloc对开辟的空间大小有严格指定,而new只需要对象名。 ⑥、malloc开辟的内存如果太小,想要换一块大一点的,可以调用relloc实现,但是new没有直观的方法来改变。
  • (8)C++有很多特有的输入输出流
  • (9)C++中有引用,而C没有。 那指针和引用有什么差别? 指针和引用的区别: ①、指针有自己的一块空间,而引用只是一个别名。 ②、使用sizeof查看一个指针大小为4(32位),而引用的大小是被引用对象的大小。 ③、指针可以是NULL,而引用必须被初始化且必须是对一个以初始化对象的引用。 ④、作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引用的修改都会改变引用所指向的对象。 ⑤、指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能被修改。 ⑥、指针可以有多级指针(**p),而引用只有一级。 ⑦、指针和引用使用++运算符的意义不一样。

参考链接

  • C 与 C++ 的区别

请说一下C/C++ 中指针和引用的区别?

  • 1.指针有自己的一块空间,而引用只是一个别名;
  • 2.使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小
  • 3.指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象 的引用;
  • 4.作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会改变引用所指向的对象
  • 5.可以有const指针,但是没有const引用
  • 6.指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能 被改变;
  • 7.指针可以有多级指针(**p),而引用至于一级;
  • 8.指针和引用使用++运算符的意义不一样;
  • 9.如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。

怎么判断一个数是二的倍数,怎么求一个数中有几个1,说一下你的思路并手写代码

  • 判断一个数是不是二的倍数,即判断该数二进制末位是不是0:
  • a % 2 == 0 或者a & 0x0001 == 0。
  • 2、求一个数中1的位数,可以直接逐位除十取余判断:
#include <iostream>
#include <memory>int judgment_function(size_t &number){int count = 0;while (number){if (number % 10 == 1){count++;}number /= 10;}return count;
}int main()
{size_t a = 11123422234411111111;std::cout << judgment_function(a) << std::endl;
}

数组和指针的区别

  • 链接:https://www.nowcoder.com/questionTerminal/68dfbfbb8dd349168b252849bf526e87
  • 数组:数组是用于储存多个相同类型数据的集合。
  • 指针:指针相当于一个变量,但是它和不同变量不一样,它存放的是其它变量在内存中的地址。

区别

  • 赋值:同类型指针变量可以相互赋值,数组不行,只能一个一个元素的赋值或拷贝
  • 存储方式:数组:数组在内存中是连续存放的,开辟一块连续的内存空间。数组是根据数组的下标进行访问的,可以随机访问。指针:指针很灵活,它可以指向任意类型的数据。指针的类型说明了它所指向地址空间的内存。
  • 求sizeof:数组所占存储空间的内存:sizeof(数组名),数组的大小 =  sizeof(数组名)/sizeof(数据类型)。在32位平台下,无论指针的类型是什么,sizeof(指针名)都是4,在64位平台下,无论指针的类型是什么,sizeof(指针名)都是8。

初始化方式不同

  • 传参方式:数组传参时,会退化为指针,C语言将数组的传参进行了退化。将整个数组拷贝一份传入函数时,将数组名看做常量指针,传数组首元素的地址。一级指针传参可以接受的参数类型:(1)可以是一个整形指针 (2)可以是整型变量地址 (3)可以是一维整型数组数组名;
  • 当函数参数部分是二级指针时,可以接受的参数类型:(1)二级指针变量(2)一级指针变量地址(3)一维指针数组的数组名

野指针

  • “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。野指针的成因主要有两种:
  • 一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
  • 二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。

C++面经 基本语言(二)

请你回答一下为什么析构函数必须是虚函数?为什么C++默认的析构函数不是虚函数 考点:虚函数 析构函数

  • 将可能会被继承的父类的析构函数设置为虚函数,可以保证new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。
  • C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。
  • 如果基类的构造函数不使用虚函数 virtual,其派生的子类都会使用父类的构造方法,不会使用自己重新定义构造函数
  • 详见  C++ 查漏补缺    使用 “多态 虚函数理论” 作为索引

请你来说一下函数指针

定义

  • 函数指针是指向函数的指针变量
  • 函数指针本身首先是一个指针变量,该指针变量指向一个具体的函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数
  • C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。

用途

  • 调用函数和做函数的参数,比如回调函数。

示例

  • char * fun(char * p)  {…}       // 函数fun
  • char * (*pf)(char * p);             // 函数指针pf
  • pf = fun;                        // 函数指针pf指向函数fun
  • pf(p);                        // 通过函数指针pf调用函数fun
#include <iostream>int max(int x,int y){return x > y ? x : y;
}int main(void)
{//p是函数指针//typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型int (*p)(int,int) = &max; //&可以省略int a = 2,b=3,c=4;/* 与直接调用函数等价,d = max(max(a, b), c) */int d = p(p(a,b),c);std::cout << "最大的数字是:"  << d << std::endl;
}

参考链接

  • 函数指针及其定义和用法,C语言函数指针详解
  • 函数指针

回调函数

函数指针作为某个函数的参数

  • 函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。
  • 简单讲:回调函数是由别人的函数执行时调用你实现的函数

以下是来自知乎作者常溪玲的解说:

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

实例

  • 实例中 populate_array 函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。
  • 实例中我们定义了回调函数 getNextRandomValue,它返回一个随机值,它作为一个函数指针传递给 populate_array 函数。
  • populate_array 将调用 10 次回调函数,并将回调函数的返回值赋值给数组。
#include <iostream>//回调函数
void populate_array(int *array,size_t array_size,int(*get_next_value)(void)){for (auto i = 0; i < array_size; ++i) {array[i] = get_next_value();}
}//获取随机数值
int get_next_value(void){return rand();
}int main(void)
{int array[10]{};/* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/populate_array(array,10,get_next_value);for (auto i = 0; i < 10; ++i) {printf("%d ",array[i]);}printf("\n");return 0;
}

请你来说一下fork函数

  • Fork:可以通过fork( )系统调用,创建一个和当前进程映像一样的进程:
  • #include <sys/types.h>
  • #include <unistd.h>
  • pid_t fork(void);
  • 成功调用fork( )会创建一个新的进程,它几乎与调用fork( )的进程一模一样,这两个进程都会继续运行。在子进程中,成功的fork( )调用会返回0。在父进程中fork( )返回子进程的pid。如果出现错误,fork( )返回一个负值。  fork函数会有两个返回值,父进程返回子进程的pid,新创建的子进程返回0,通过返回值确定当前进程是父亲还是孩子。如果出现错误,返回负数。
  • 最常见的fork( )用法是创建一个新的进程,然后使用exec( )载入二进制映像,替换当前进程的映像(起一个进程执行用户指定的程序)。这种情况下,派生(fork)了新的进程,而这个子进程会执行一个新的二进制可执行文件的映像。这种“派生加执行”的方式是很常见的。
  • 在早期的Unix系统中,创建进程比较原始。当调用fork时,内核会把所有的内部数据结构复制一份,复制进程的页表项,然后把父进程的地址空间中的内容逐页的复制到子进程的地址空间中。但从内核角度来说,逐页的复制方式是十分耗时的。现代的Unix系统采取了更多的优化,例如Linux,采用了写时复制的方法,而不是对父进程空间进程整体复制
  • 每个进程都有一个独特(互不相同)的进程标识符(process ID),可以通过getpid()函数获得

参考链接

  • fork(2) — Linux manual page
  • linux中fork()函数详解(原创!!实例讲解)

 请你来说一下C++中析构函数的作用

  • 析构函数与构造函数对应,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。
  • 析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。
  • 如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。
  • 如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏
  • 类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数
  • 将基类的析构函数弄成虚函数的形式,派生类继承基类的析构函数,并对其进行函数的重载。适用于使用数组存储多个对象的情形,只能使用派生类自定义的析构函数,释放其申请的内存空间。
  • 什么时候需要自定义析构函数?比如在堆上申请了一大段内存空间,使用delete []p,进行资源的释放
  • delete 对象,先调用用户自定义的析构函数,再调用编译系统自动生成的缺省的析构函数
#include <iostream>
#include <fstream>
#include <sstream>class Car{
public:Car(){m_pName = new char [20];std::cout << " 对象创建" << std::endl;};~Car(){delete[] m_pName;std::cout << " 对象销毁 " << std::endl;}
private:char *m_pName;
};
int main(void)
{Car *car = new Car();delete car;car = nullptr;return 0;
}

请你来说一下静态函数和虚函数的区别

  • 静态函数在编译的时候就已经确定运行时机虚函数在运行的时候动态绑定虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销
  • 类的静态函数是没有this指针的,调用它时不需要创建对象,通过:类名 ::函数名(参数)的形式直接调用。静态函数只有唯一的一份,因此它的地址是固定不变的, 所以编译的时候但凡遇到调用该静态函数的时候就知道调用的是哪一个函数,因此说静态函数在编译的时候就已经确定运行时机
  • 类A与类B构成多态,创建了 A类指针pb指向 B类对象,当程序编译的时候只对语法等进行检测,该语句没有什么问题,但是编译器此时无法确定调用的是哪一个 fun() 函数,因为类A类B中都含有fun函数,因此只能是在程序运行的时候通过 pb指针 查看对象的虚函数表(访问虚函数表就是所谓的访问内存 内存)才能确定该函数的地址,即确定调用的是哪一个函数。这就解释了所说的“虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销
#include <iostream>class A{
public:virtual void fun(){std::cout << " A " << std::endl;}
};class B : public A{
public:virtual void fun(){std::cout << " B " << std::endl;}
};int main(void)
{A a{};B b{};A* pb = &b;pb->fun();a.fun();b.fun();return 0;
}

参考链接

  • C++ 静态函数与虚函数的区别

面向对象的三个基本特征

  • 封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用

封装

  • 封装:就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。

继承

  • 继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力

多态

  • 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

参考链接

  • C++—继承与多态
  • C++基础复习

请你来说一说重载和覆盖

  • 重载:一个类中,两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求,在同一作用域中
  • 重写:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写

请你来说一说static关键字

  • 1.加了static关键字的全局变量只能在本文件中使用。例如在a.c中定义了static int a=10;那么在b.c中用extern int a是拿不到a的值,a的作用域只在a.c中。
  • 2.static定义的静态局部变量分配在数据段上,普通的局部变量分配在栈上,会因为函数栈帧的释放而被释放掉。
  • 3. 对一个类中成员变量和成员函数来说,加了static关键字,则此变量/函数就没有了this指针了,必须通过类名才能访问

 请你说一说strcpy和strlen

  • strcpy是字符串拷贝函数,原型:  char *strcpy(char* dest, const char *src);
  • 从src逐字节拷贝到dest,直到遇到'\0'结束,因为没有指定长度,可能会导致拷贝越界,造成缓冲区溢出漏洞,安全版本是strncpy函数
  • strlen函数是计算字符串长度的函数,返回从开始到'\0'之间的字符个数

请你说一说你理解的虚函数和多态

  • 多态的实现主要分为静态多态和动态多态静态多态主要是重载,在编译的时候就已经确定动态多态是用虚函数机制实现的,在运行期间动态绑定
  • 举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了virtual关键字的函数,在子类中重写时候不需要加virtual也是虚函数。
  • 虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。

请你来回答一下++i和i++的区别

  • ++i先自增1,再返回,i++先返回i,再自增1
  • ++i 实现
int&  int::operator++()
{
*this +=1;
return *this;
}
  • i++
const int  int::operator(int)
{
int oldValue = *this;
++(*this);
return oldValue;
}

请你来写个函数在main函数执行前先运行

#include<iostream>__attribute((constructor))void before()
{printf("before main\n");
}int main(){std::cout << "main 函数!" << std::endl;
}

有段代码写成了下边这样,如果在只修改一个字符的前提下,使代码输出20个hello?

  • for(int i = 0; i < 20; i--) cout << "hello" << endl;
#include<iostream>int main(){for(int i = 0; i + 20; i--)std::cout << i << " hello" << std::endl;
}

请你来说一下智能指针shared_ptr的实现

参考链接

  • C++11 shared_ptr智能指针(超级详细)
  • 智能指针shared_ptr实现

以下四行代码的区别是什么?

  • const char * arr = "123"; char * brr = "123"; const char crr[] = "123"; char drr[] = "123";

  • const char * arr = "123";  //字符串123保存在常量区,const本来是修饰arr指向的值不能通过arr去修改,但是字符串“123”在常量区,本来就不能改变,所以加不加const效果都一样
  • char * brr = "123";  //字符串123保存在常量区,这个arr指针指向的是同一个位置,同样不能通过brr去修改"123"的值
  • const char crr[] = "123";  //这里123本来是在栈上的,但是编译器可能会做某些优化,将其放到常量区
  • char drr[] = "123";   //字符串123保存在栈区,可以通过drr去修改

 请你来说一下C++里是怎么定义常量的?常量存放在内存的哪个位置?

  • 常量在C++里的定义就是一个top-level const加上对象类型,常量定义必须初始化
  • 对于局部对象,常量存放在栈区,
  • 对于全局对象,常量存放在全局/静态存储区。
  • 对于字面值常量,常量存放在常量存储区。
  • 会被人打的方式:#define CONSTANT value
  • 高级一点的方式:const auto constant = value;
  • 最新潮的方式:constexpr auto constant = value;

补充知识

  • constexpr是c++11新添加的特征,目的是将运算尽量放在编译阶段,而不是运行阶段。这个从字面上也好理解,const是常量的意思,也就是后面不会发生改变,因此当然可以将计算的过程放在编译过程。constexpr可以修饰函数、结构体。
  • constexpr用法
  • 才搞清楚常量的存储位置

请你来回答一下const修饰成员函数的目的是什么?

  • const修饰的成员函数表明函数调用不会对对象做出任何更改,事实上,如果确认不会对对象做更改,就应该为函数加上const限定,这样无论const对象还是普通对象都可以调用该函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446571.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++STL与泛型编程(4)OOP(面向对象编程) Vs. GP(泛型编程)

文章目录OOP和GP为什么list不能使用标准库中的::sort算法&#xff1f;采用GP的好处OOP和GP OOP将datas和methods关联在一起 GP将datas和methods分开 为什么list不能使用标准库中的::sort算法&#xff1f; 因为标准库的sort的算法用到了随机访问迭代器&#xff08;RandomAcce…

牛客网 链表结构 算法相关内容

链表结构 单链表的节点结构 由以下结构的节点依次连接起来所形成的链叫单链表结构 Clas Node<V>{ V value; Node next; } 双链表的节点结构 由以下结构的节点依次连接起来所形成的链叫双链表结构 Clas Node<V>{ V value; Node next; Node last; } 单链表和双…

C++ primer 第8章 IO库

文章目录IO库类型和头文件IO对象无拷贝或赋值IO流的条件状态文件输入输出ifstream 示例ofstream 示例文件模式以out模式打开文件会丢弃已有数据每次调用open时都会确定文件模式ofstream 保留源文件 追加数据 示例string流istringstream示例ostringstream示例IO库类型和头文件 …

C++面试宝典 基本语言(三)

如果同时定义了两个函数&#xff0c;一个带const&#xff0c;一个不带&#xff0c;会有问题吗&#xff1f; 不会&#xff0c;这相当于函数的重载 #include<iostream> class A{ public:void print()const{std::cout << "Hello" << std::endl;}void…

C++ primer 第9章 顺序容器

文章目录顺序容器类型确定使用哪种顺序容器容器库概览容器操作迭代器迭代器支持的所有操作迭代器支持的所有运算迭代器范围对构成范围的迭代器的要求标准库迭代器范围左闭右开的三种性质容器定义和初始化将一个新容器创建为另一个容器的拷贝将array拷贝到vector中的代码与顺序容…

牛客网C++面经 容器和算法

原文网址 参考网址 C语言中文网 请你来说一下map和set有什么区别&#xff0c;分别又是怎么实现的&#xff1f; map和set都是C的关联容器&#xff0c;其底层实现都是红黑树&#xff08;RB-Tree&#xff09;。由于 map 和set所开放的各种操作接口&#xff0c;RB-tree 也都提供…

C++ primer 第10章 泛型算法

文章目录概述findcount初识泛型算法只读算法只读算法accumulate只读算法equal写容器元素的算法算法fill算法fill_nback_inserter算法copy算法replace replace_copy重排容器元素的算法sortuniqueunique_copy定制操作向算法传递函数谓词算法stable_sort算法partitionlambda表达式…

C语言常用字符串函数

概括 代码 #include<stdlib.h> #include<stdio.h> #include<string.h> int main() {//常用字符串函数char a[]"abcSDFbnm";char b[]"SD";printf("a的字符串长度:%d\n",strlen(a));printf("b的字符串长度:%d\n",str…

C++ primer 第11章 关联容器

文章目录使用关联容器map示例关联容器概述定义关联容器关联容器值初始化multimap和multiset关键字类型的要求pair类型pair上的操作关联容器操作关联容器额外的类型别名关联容器迭代器map迭代器set迭代器关联容器和算法添加元素向map添加元素检测insert的返回值使用insert代替下…

C++ primer 第12章 动态内存

文章目录前言动态内存与智能指针shared_ptr类shared_ptr和unique_ptr都支持的操作shared_ptr独有的操作make_shared 函数shared_ptr的拷贝和赋值shared_ptr自动销毁所管理的对象shared_ptr还会自动释放相关联的内存程序使用动态内存出于以下原因直接管理内存使用new动态分配和初…

C语言顺序查找二分查找

介绍 顺序查找 按照顺序一个个查找 #include<stdio.h> //顺序查找 int search(int arr[],int len,int aim) {int i;for(i0;i<len;i){if(arr[i]aim){return i;//返回下标 }}return -1;//表示未查询到} int main() {int arr[]{13,355,256,65,234,-1,35,-6,-3,-4,0};…

C++ primer 第12章 12.3 使用标准库:文本查询程序

文章目录使用标准库&#xff1a;文本查询程序文本查询程序设计数据结构在类之间共享数据自己的文本查询程序书中的文本查询程序使用标准库&#xff1a;文本查询程序 我们将实现一个简单的文本查询程序&#xff0c;作为标准库相关内容学习的总结。 我们的程序允许用户在一个给…

C语言二维数组 int arr[2][3]

基础使用 先遍历行再遍历列 #include<stdio.h> //二维数组的基本使用 int main() {//二维数组的初始化int arr1[2][2]{{2,2},{0,0}};int arr2[2][3]{2,2,2,8,8,8};int arr3[6][9];int i,j;for(i0;i<6;i){for(j0;j<9;j){arr3[i][j]1;}}arr3[2][5]0;//打印printf(&…

C++ primer 第13章 拷贝控制

文章目录前言拷贝、赋值与销毁拷贝构造函数合成拷贝构造函数拷贝初始化和直接初始化拷贝初始化的发生&#xff1a;参数和返回值拷贝初始化的限制拷贝赋值运算符重载赋值运算符合成拷贝赋值运算符析构函数析构函数完成的工作什么时候会调用析构函数合成析构函数代码片段调用几次…

C语言 指针自增自减加减运算 p++ p+i

介绍 自增自减代码 #include<stdio.h> #include<string.h> //指针自增--short void increase(short *arr,int len) {int i;arr&arr[0];for(i0;i<len;i){printf("arr[%d]%d,address%p\n",i,*arr,arr);arr;} }//指针自减--char void decrease(char…

C++ 编译与底层

原文链接 编译与底层请你来说一下一个C源文件从文本到可执行文件经历的过程&#xff1f; 对于C源文件&#xff0c;从文本到可执行文件一般需要四个过程&#xff1a;预处理阶段&#xff1a;对源代码文件中文件包含关系&#xff08;头文件&#xff09;、预编译语句&#xff08;…

C语言 指针数组-字符指针数组整型指针数组 char*s[3] int*a[5] 数组指针int(*p)[4]

基本介绍 1.指针数组:由n个指向整型元素的指针而组成,里面存放指针 Int *ptr[3]; 2.地址: ptr[i]:元素地址 &ptr[i]:指针地址 图示 代码: 内存布局: 代码 #include<stdio.h> #include<string.h> //指针数组--int void pointer(int *arr,int len) {int …

C语言 多重指针--整型字符字符串 int**pp

介绍 多重指针:一个指针指向另一个指针 离值越近的指针级别越大:一级 内存布局 代码 图示: 多重指针–整型 #include<stdio.h> #include<string.h> //多重指针--整型//二级指针 void two() {printf("二级指针:\n");int a896;int *p&a,**pp&…

C++ primer 第13章 拷贝控制

文章目录前言拷贝、赋值与销毁拷贝构造函数合成拷贝构造函数拷贝初始化和直接初始化拷贝初始化的发生&#xff1a;参数和返回值拷贝初始化的限制拷贝赋值运算符重载赋值运算符合成拷贝赋值运算符析构函数析构函数完成的工作什么时候会调用析构函数合成析构函数代码片段调用几次…

牛客网C++面经 C++11

请问C11有哪些新特性&#xff1f; auto关键字&#xff1a;编译器可以根据初始值自动推导出类型。但是不能用于函数传参以及数组类型的推导nullptr关键字&#xff1a;nullptr是一种特殊类型的字面值&#xff0c;它可以被转换成任意其它的指针类型&#xff1b;而NULL一般被宏定义…