程序员面试——C++工程师面试大全第一部分

1.static 关键字的作用

1. 全局静态变量

在全局变量前加上关键字 static,全局变量就定义成一个全局静态变量.

静态存储区,在整个程序运行期间一直存在.

初始化:未经初始化的全局静态变量会被自动初始化为 0(自动对象的值是任意的,除非他 被显式初始化);

作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾.

2. 局部静态变量

在局部变量之前加上关键字 static,局部变量就成为一个局部静态变量.

内存中的位置:静态存储区

初始化:未经初始化的全局静态变量会被自动初始化为 0(自动对象的值是任意的,除非他被显式初始化);

作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束.但 是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对 它进行访问,直到该函数再次被调用,并且值不变;

扫描二维码关注公众号,回复: 9387654 查看本文章

3. 静态函数

在函数返回类型前加 static,函数就定义为静态函数.函数的定义和声明在默认情况下都 是 extern 的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用.

函数的实现使用 static 修饰,那么这个函数只可在本 cpp 内使用,不会同其他 cpp 中的同 名函数引起冲突;

warning:不要再头文件中声明 static 的全局函数,不要在 cpp 内声明非 static 的全局函 数,如果你要在多个 cpp 中复用该函数,就把它的声明提到头文件里去,否则 cpp 内部声明需加 上 static 修饰;

4.类的静态成员

在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐 藏的原则,即保证了安全性.因此,静态成员是类的所有对象中共享的成员,而不是某个对象的 成员.对多个对象来说,静态数据成员只存储一处,供所有对象共用

5. 类的静态函数

静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员.因此, 对静态成员的引用不需要用对象名.

在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成 员(这点非常重要).如果静态成员函数中要引用非静态成员时,可通过对象来引用.从中可看 出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);

2.C++和 C 的区别

设计思想上:

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

语法上:

C++具有重载,继承和多态三种特性

C++相比 C,增加多许多类型安全的功能,比如强制类型转换,

C++支持范式编程,比如模板类,函数模板等

3.C++中四种 cast 转换

C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast

1,const_cast 用于将 const 变量转为非 const

2,static_cast 用于各种隐式转换,比如非 const 转 const,void*转指针等, static_cast 能用于多态向上 转化,如果向下转能成功但是不安全,结果未知;

3,dynamic_cast 用于动态类型转换.只能用于含有虚函数的类,用于类层次间的向上和向下转化.只能转指 针或引用.向下转化时,如果是非法的对于指针返回 NULL,对于引用抛异常.要深入了解内部 转换的原理. 向上转换:指的是子类向基类的转换 向下转换:指的是基类向子类的转换 它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否 能够进行向下转换.

4,reinterpret_cast 几乎什么都可以转,比如将 int 转指针,可能会出问题,尽量少用;

5,为什么不使用 C 的强制转换? C 的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查, 容易出错.

4.C/C++ 中指针和引用的区别

1.指针有自己的一块空间,而引用只是一个别名;

2.使用 sizeof 看一个指针的大小是 4,而引用则是被引用对象的大小;

3.指针可以被初始化为 NULL,而引用必须被初始化且必须是一个已有对象 的引用;

4.作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会 改变引用所指向的对象;

5.可以有 const 指针,但是没有 const 引用;

6.指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能 被改变;

7.指针可以有多级指针(**p),而引用至于一级;

8.指针和引用使用++运算符的意义不一样;

9.如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露.

5.你说一下你理解的 c++中的 smart pointer 四个智能指针: shared_ptr,unique_ptr,weak_ptr,auto_ptr

C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是 c++11 支持,并且第一个已经被 11 弃用.

为什么要使用智能指针: 智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏.使用智能指针可以很大程度上的避免这个问题,因为智能指针就是一个类, 当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源.所以智能指针的作 用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间.

1. auto_ptr(c++98 的方案,cpp11 已经抛弃) 采用所有权模式.

auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”));

auto_ptr<string> p2;

p2 = p1; //auto_ptr 不会报错.

此时不会报错,p2 剥夺了 p1 的所有权,但是当程序运行时访问 p1 将会报错.所以 auto_ptr 的缺点是:存在潜在的内存崩溃问题!

2. unique_ptr(替换 auto_ptr)

unique_ptr 实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象.它对于避免资源泄露(例如“以 new 创建对象后因为发生异常而忘记调用 delete”)特 别有用.

采用所有权模式,还是上面那个例子

unique_ptr<string> p3 (new string ("auto")); //#4

unique_ptr<string> p4; //#5

p4 =p3;//此时会报错!!

编译器认为 p4=p3 非法,避免了 p3 不再指向有效数据的问题.因此,unique_ptr 比 auto_ptr 更安全.

另外 unique_ptr 还有更聪明的地方:当程序试图将一个 unique_ptr 赋值给另一个时,如 果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做,比如:

unique_ptr<string>pu1(“hello world”);

unique_ptr<string>pu2;

pu2=pu1; //#1not allowed

unique_ptr<string>pu3;

pu3=unique_ptr<string>(“you”); //#2 allowed

其中#1 留下悬挂的 unique_ptr(pu1),这可能导致危害.而#2 不会留下悬挂的 unique_ptr, 因为它调用 unique_ptr 的构造函数,该构造函数创建的临时对象在其所有权让给 pu3 后就会 被销毁.这种随情况而已的行为表明,unique_ptr 优于允许两种赋值的 auto_ptr .

注:如果确实想执行类似与#1 的操作,要安全的重用这种指针,可给它赋新值.C++有一个 标准库函数 std::move(),让你能够将一个 unique_ptr 赋给另一个.例如:

unique_ptr<string>ps1,ps2;

ps1=demo(“hello”);

ps2=move(ps1);

ps1=demo(“Alexia”);

cout<<*ps2<<*ps1<<endl;

3. shared_ptr

shared_ptr实现共享式拥有概念.多个智能指针可以指向相同对象,该对象和其相关资源 会在“最后一个引用被销毁”时候释放.从名字 share 就可以看出了资源可以被多个指针共享, 它使用计数机制来表明资源被几个指针共享.可以通过成员函数 use_count()来查看资源的所有 者个数.除了可以通过 new 来构造,还可以通过传入 auto_ptr, unique_ptr,weak_ptr 来构造. 当我们调用 release()时,当前指针会释放资源所有权,计数减一.当计数等于 0 时,资源会被释放.

shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的), 在使 用引用计数的机制上提供了可以共享所有权的智能指针.

成员函数: use_count 返回引用计数的个数 unique 返回是否是独占所有权( use_count 为 1) swap 交换两个 shared_ptr 对象(即交换所拥有的对象) reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少 get 返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样的.如 shared_ptr<int> sp(new int(1)); sp 与 sp.get()是等价的

4.weak_ptr

weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的 shared_ptr. weak_ptr 只是提供了对管理对象的一个 访问手段.weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析 构不会引起引用记数的增加或减少.weak_ptr 是用来解决 shared_ptr 相互引用时的死锁问题, 如果说两个 shared_ptr 相互引用,那么这两个指针的引用计数永远不可能下降为 0,资源永远不 会释放.它是对对象的一种弱引用,不会增加对象的引用计数,和 shared_ptr 之间可以相互转化,shared_ptr 可以直接赋值给它,它可以通过调用lock函数来获得 shared_ptr.

6.野指针是什么?

野指针就是指向一个已删除的对象或者未申请访问受限内存区域的指针

7.介绍一下 C++中的智能指针

智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象.当栈对象的 生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏.C++ 11 中最常用的 智能指针类型为 shared_ptr,它采用引用计数的方法,记录当前内存资源被多少个智能指针引用. 该引用计数的内存在堆上分配.当新增一个时引用计数加 1,当过期时引用计数减一.只有引用 计数为 0 时,智能指针才会自动释放引用的内存资源.对 shared_ptr 进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类.可以通过 make_shared 函数或者通 过构造函数传入普通指针.并可以通过 get 函数获得普通指针.

8.为什么析构函数必须是虚函数?为什么 C++默认的析构函数不是虚函数

将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们 new 一个子类,然后使用 基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏.

C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存.而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存.因此 C++默认的 析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数.

9.说一下函数指针

1,定义

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

2,用途:

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

3,示例:

char * fun(char * p) {…} // 函数 fun

char * (*pf)(char * p); // 函数指针 pf

pf = fun; // 函数指针 pf= fun

pf(p); // 通过函数指针 pf 调用函数 fun

10.说一下 fork 函数

Fork:创建一个和当前进程映像一样的进程可以通过 fork( )系统调用:

#include <sys/types.h>

#include <unistd.h>

pid_t fork(void);

成功调用 fork( )会创建一个新的进程,它几乎与调用 fork( )的进程一模一样,这两个进 程都会继续运行.在子进程中,成功的 fork( )调用会返回 0.在父进程中 fork( )返回子进程 的 pid.如果出现错误,fork( )返回一个负值.

最常见的 fork( )用法是创建一个新的进程,然后使用 exec( )载入二进制映像,替换当前进程的映像.这种情况下,派生(fork)了新的进程,而这个子进程会执行一个新的二进制可执 行文件的映像.这种“派生加执行”的方式是很常见的.

在早期的 Unix 系统中,创建进程比较原始.当调用 fork 时,内核会把所有的内部数据结构 复制一份,复制进程的页表项,然后把父进程的地址空间中的内容逐页的复制到子进程的地址空 间中.但从内核角度来说,逐页的复制方式是十分耗时的.现代的 Unix 系统采取了更多的优化, 例如 Linux,采用了写时复制的方法,而不是对父进程空间进程整体复制.

发布了374 篇原创文章 · 获赞 194 · 访问量 51万+

猜你喜欢

转载自blog.csdn.net/qq_32146369/article/details/104474749