C++面试问答总结

​​​​​​​C++ 在线工具 | 菜鸟工具

1.独占指针和const的区别?

独占指针是一种智能指针,同一时间只能有一个独占指针,指向某个特定对象,自动释放所指向对象的内存,不可以拷贝复制;

const是修饰符,表示变量的不可修改,修饰类的成员函数时,表示该函数不修改对象状态,该函数可以被const对象调用;

2.智能指针介绍;

share_ptr:共享式智能指针,使用计数机制自动管理内存的释放,允许多个shared_ptr对象共享同一个资源,适用于多个对象需要共享同一资源场景,比如多个模块需要访问同一个配置文件对象;

unique_ptr:独占式指针,保证所管理的对象只能有一个所有者,离开作用域时,它会自动释放所指向资源,不能拷贝复制,但可以移动,适用于管理动态分配的单个对象,例如在函数内部动态分配一个对象并返回给调用者;

weak_ptr:弱引用智能指针,不参与资源的引用计数,解决share_ptr的循环引用问题,用weak_ptr观察shared_ptr所管理的对象,不会影响对象的生命周期,当shared_ptr所管理的对象被释放后,weak_ptr会自动变为空指针;

使用智能指针有效防止内存泄漏;智能指针还可以用于管理其他类型的资源,如文件句柄、网络连接等。当智能指针离开作用域时,会自动关闭文件或断开网络连接,确保资源的正确释放;函数可以返回智能指针,将资源的所有权转移给调用者,由调用者负责资源的释放,使代码更加清晰和安全;

  • 容器类对象:在容器中存储对象指针时,使用智能指针可以方便地管理容器中对象的生命周期。当对象从容器中移除或容器本身被销毁时,智能指针会自动释放对象。

3.强制类型转换;

动态类型转换dynamic_cast:

静态类型转换static_cast:

常量类型转换const_cast:

4.左右值区别,移动语义

左值在程序运行时有确定内存地址,右值是临时对象,没有内存地址的值;

移动语义通过“移动构造函数”和“移动赋值操作符”引入,目的是从右值中“窃取”资源,而不是复制资源,从而提高程序效率。

  1. 移动构造函数
    • 用于从右值对象中“移动”资源到新创建的对象中。
    • 它的典型签名是:ClassName(ClassName&& other);
    • 移动构造函数通常会将源对象的资源指针置为nullptr或其他有效但为空的状态,以避免资源重复释放。
  2. 移动赋值操作符
    • 用于将右值对象的资源“移动”到左值对象中。
    • 它的典型签名是:ClassName& operator=(ClassName&& other);
    • 同样,需要确保源对象处于有效但未定义的状态。
  3. std::move
    • std::move是一个标准库函数,用于将一个左值强制转换为右值引用,从而可以对其执行移动操作。
    • 需要注意的是,std::move并不真正“移动”任何内容,它只是进行了一个类型转换。
  4. 使用场景
    • 当涉及到大量数据或需要频繁复制的对象时(如容器、字符串等),移动语义可以显著提高性能。
    • 移动语义避免了不必要的深拷贝,减少了内存分配和释放的开销。

5.析构函数为什么定义为虚函数?

保证父类指针指向子类对象时,子类的析构函数可以被调用,释放内部内存;

6.sizeof(int),sizeof(指针)?

32位:4,4;

64位:4,8

7.优先队列priority_queue使用?

小顶堆(greater),大顶堆(less)

8.deque和queue区别?

双端队列(可以直接读取两头位置),单端队列

9.decltype查询类型?

decltype是C++11引入的一个关键字,用于查询表达式的类型,并在编译时返回该类型。这在泛型编程和模板编程中尤为有用,因为它允许程序员在不明确指定类型的情况下获取表达式的类型。

10.Vector的内存管理?

clear();//清空size

resize();//设定size大小

reserve();//设定capacity大小

shrink_to_fit();//设置容器的capacity向size大小缩小;

与空容器swap(vector<int>());//彻底清空容器内存;

push_back元素时,如果内存足够,内存不变;如果内存不够,vector会重新申请一块二倍的size大小的capacity空间,将原来的元素拷贝(移动)复制过去,将要push的元素对应拷贝(移动)复制过去,清除掉之前占用的内存空间;

11.emplace_back()和push_back()的区别?

push_back() 用于将一个已存在的对象添加到容器的尾部。如果传递的是对象本身,会调用对象的拷贝构造函数;如果传递的是右值(如临时对象),则会调用移动构造函数。如果对象不存在,则会先创建一个临时对象,再进行拷贝或者移动;

emplace_back() 允许直接在容器的尾部构造对象,而不需要先创建一个临时对象再进行拷贝或移动。它会直接在容器的内存空间中调用对象的构造函数,避免了不必要的拷贝或移动操作,提高了性能。

区别总结

  • 性能方面emplace_back() 通常比 push_back() 更高效,尤其是对于构造复杂对象或需要动态分配内存的对象,因为它避免了不必要的拷贝或移动操作。
  • 使用方式push_back() 接受一个已存在的对象作为参数,而 emplace_back() 接受构造对象所需的参数,直接在容器内部构造对象。

应用场景

  • push_back():当你已经有一个现成的对象,并且想要将其添加到容器中时,使用 push_back() 比较合适。
  • emplace_back():当你需要在容器中创建新对象,并且希望避免不必要的拷贝或移动开销时,应该优先使用 emplace_back()。特别是在处理大型对象或自定义类型时,emplace_back() 的性能优势会更加明显。

12.stoll()将字符串转为long long类型

13.如何有效防止栈溢出?

在 C++ 中,栈溢出通常是由于栈空间被过度使用导致的,常见原因包括递归调用过深、在栈上创建过大的局部变量等。

(1)优化递归算法,迭代替代递归;

(2)控制递归深度;

(3)避免在栈上创建过大的局部变量,将大对象分配到堆上使用动态内存分配

#include <iostream>

// 在栈上创建大数组(可能导致栈溢出)
// const int SIZE = 1000000;
// int stackArray[SIZE];

// 在堆上创建大数组
const int SIZE = 1000000;
int* heapArray = new int[SIZE];

int main() {
    // 使用堆上的数组
    for (int i = 0; i < SIZE; ++i) {
        heapArray[i] = i;
    }

    // 释放堆上的内存
    delete[] heapArray;

    return 0;
}

14.如何优化代码内存消耗?

结构体表达使用;

避免不必要的拷贝构造,比如函数传参引用;

代码设计,提高时间复杂度,空间复杂度;

15.指针函数,函数指针

指针函数:函数的返回值是指针;

函数指针:有一个指针指向函数,可以直接使用指针调用函数,比如回调函数的使用;

16.内联函数inline的使用,内联函数可以递归吗?可以为虚函数吗?

内联函数不可以递归,也不可以为虚函数,因为内联函数需在编译时候会在函数调用位置展开,递归会导致代码过于膨胀,虚函数在运行时确定调用函数,所以不可以;

17.模板函数可以为虚函数吗?

不可以,跟内联函数原因一致,模板函数在编译期间确定模板类型;

18.C与C++的struct的区别?

struct在C中没有访问权限概念,所有成员都是公共的访问权限的概念,C++(默认是public)可以设置访问权限private, protected。

19.C++中,class与struct的区别?

class默认访问权限是private,struct默认是public;struct一般用于简单数据结构的聚合,class侧向面向对象的特性,封装继承多态这些;

20.排序的效率,哈希表红黑树的理解?

红黑树的底层结构是二叉搜索树;

21.锁的使用

(1)std::mutex 互斥锁

构造函数:不允许拷贝构造,不允许move拷贝,默认unlocked状态;

lock()函数:调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
如果该互斥量当前没 有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
如果当 前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
如果当前互斥量被当前调用线程锁 住,则会产生死锁(deadlock)。

unlock()函数:解锁,释放对互斥量的所有权

try_lock()函数:尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该 函数也会出现下面 3 种情况:
如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直 到该线程调用 unlock 释放互斥量。
如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。

(2)std::lock_guard  条件锁

(3)std::condition_variable 同步条件变量

参考:

C++锁的使用_c++ 锁-优快云博客

21.如何排查bug

gdb调试的使用

Visual Studio Code (VSCode) 使用 GDB 进行调试_vscode使用gdb调试-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值