C++常见问题整理

最近用C++面试刷题,简单整理了一些心得和知识点,希望也能帮助到使用C++的你,有什么建议欢迎留言!

虚函数 & 纯虚函数 & override

  • 声明为virtual,从而在调用指向子类对象的基类指针时,会调用子类对象的相应方法;否则只会调用基类的方法
  • 声明为virtual并在结尾加上 = 0,基类不实现该函数
  • override不是一个强制的关键词,但是是一个良好的编程习惯,加了override,编译器会检查是否真的重写了相应的函数(如函数名,参数列表是否一致)

多态

  • 静态多态 — 编译阶段,多通过函数重载(同名函数)和模板实现
  • 动态多态 — 运行阶段,多通过虚函数
  • 区别,什么时候将函数实现和函数调用关联起来

vtable,虚表

每个类(注意不是实例),拥有一个vtable指向该类的所有函数地址

C++11 smart pointer

weak_ptr是为了解决shared_ptr循环引用导致死锁资源不释放的问题

STL

vector

  • 头文件:#include <vector>
  • 底层为数组
  • 构造函数
    • 常规 — vector<int> a;
    • 初始化 — vector<int> a(4, 0),长度为4,全零
  • 访问
    • [index] 或者 .at(index)
    • .data()获得底层指针
  • 插入
    • push_back
    • iterator insert(iterator, n)
  • 删除
    • pop_back — 删除最后一个
    • iterator erase(iterator)
  • 注意iterator的使用,比如insert和erase都是接收iterator为参数,并返回新的iterator(迭代的时候一定要注意更新iterator)
  • begin & end — 获得开始和结尾的iterator

list

  • 头文件:#include<list>
  • 底层为doubly-linked list
  • 和vector很像,额外有push/pop_front/back(可以头插和尾插)
  • remove — 删除某些具体元素(如:remove(89),删除数组里面所有等于89的元素)

stack

  • 头文件:#include <stack>
  • empty — 是否为空
  • size — 返回stack的大小
  • push — 插入一个元素
  • top — 返回最上面的元素
  • pop — 单纯的删除最上面的元素,一般与top结合使用
  • emplace — 构造并传入一个对象
  • swap — 交换两个stack的内容

queue

  • 头文件:#include <queue>
  • empty
  • size
  • front + back
  • push — 插入一个新的元素
  • pop — 单纯删除第一个元素,一般与front结合使用

priority_queue

  • 头文件:#include <queue>
  • 底层是heap
  • empty
  • size
  • top
  • pop
  • push

自定义一个Comparator并传入

class mycomparison
{
  bool reverse;
public:
  mycomparison(const bool& revparam=false)
  {
    reverse=revparam;
  }
  bool operator() (const int& lhs, const int&rhs) const
  {
    if (reverse) return (lhs>rhs);
    else return (lhs<rhs);
  }
};

std::priority_queue<int, std::vector<int>, mycomparison> pq;

map & unordered_map

  • 头文件:#include <map>, #include <unordered_map>
  • map底层为红黑树,unordered_map底层为哈希表
  • map — TreeMap,有序
  • unordered_map — HashMap,无序
std::map<char, int> myMap;
// 插入
myMap.insert(std::pair<char, int>('a', 1));
// 访问
cout << myMap['a'];
// 查找
if(myMap.find('b') != myMap.end()){
  cout << "found";
}else{
  cout << "not found";
}
// 等价于
if(myMap.count('b') > 0){
  cout << "found";
}else{
  cout << "not found";
}
// 正向遍历
std::map<char,int>::iterator it;
for (it=myMap.begin(); it!=myMap.end(); ++it){
  std::cout << it->first << " => " << it->second << '\n';
}
// 反向遍历
std::map<char,int>::reverse_iterator rit;
for (rit=myMap.rbegin(); rit!=myMap.rend(); ++rit){
  std::cout << rit->first << " => " << rit->second << '\n';
}
// 注意单纯的end()返回的是最后一个元素后面一个位置,要想获得最后一个元素,要用rbegin()
  • unordered_map基本一样,除了没有rbegin(因为本身是无序的)

set & unordered_set

  • 头文件:#include <set>, #include <unordered_set>
  • set底层为红黑树,unordered_set底层为hash table
  • insert
  • erase
  • count
  • find
  • 基本和map很像

pair

  • #include <utility>
  • first + second
std::pair<std::string, double> product1; 
product1.first = "hello";
product1.second = 3.3;
auto product2 = std::make_pair(10, 2);

tuple

  • #include <tuple>
  • get<index>(tuple)
std::tuple<int,char> mytuple (10,'a');

std::get<0>(mytuple) = 20;
auto t = std::make_tuple(10, 2, 'a', "test");

迭代器(iterator)

本质就是指针

容器类插入删除
list所有迭代器不失效有且仅有被删除的节点迭代器失效
vector如果size不变(没有扩容),则插入元素之后的所有迭代器都失效;否则全部失效被删除节点之后的迭代器全部失效
set/map所有迭代器不失效有且仅有被删除的节点迭代器才失效

常用头文件

  • #include <algorithm>sort排序

  • #include <functional> — greater,less,greater_equal

  • #include <sstream> — stringstream

    • 可以理解为动态string(可以动态修改内容但不会触发拷贝)

    •   std::stringstream ss;
        ss << 100 << ' ' << 200;
        
        int foo,bar;
        ss >> foo >> bar;
      
  • #include <utility> — pair

  • #include <math.h> — floor, pow, ceil

常用snippet

排序(调用系统函数)

#include <algorithm>
sort(v.begin(), v.end()); // 递增
sort(v.begin(), v.end(), std::greater<int>()); // 递减
//自定义结构体排序
struct Node
{
	  int a;
	  int b;
};
bool cmp(Node x, Node y)
{
	  return x.a<y.a;
}
vector<Node> v;
sort(v.begin(), v.end(), cmp);

读取二维数组

class Node{
public:
    int value;
    bool visited;
    
    Node() : value(0), visited(true){};
};

int main(void)
{
    int row, col;
    cin >> row >> col;
    vector<vector<Node>> matrix(row, vector<Node>(col));
    for(int i = 0; i < row; i++){
        for(int j = 0; j < col; j++){
            cin >> matrix[i][j].value;
        }
    }
    // do whatever you want
    return 0;
}

输入输出

  • getline — getline(cin, line, ‘\n’),最后一个参数是分隔符,可用来分隔一行(逗号分隔)
  • stringstream — items >> str,可用>>提取字符串或者数字,但是前提是空格分隔

逐行读取(每行有2个数字)

#include <iostream>
#include <sstream>

using namespace std;

int main(){
    int a = 0; 
    int b = 0;
    string line;
    while(getline(cin, line, '\n')){
        stringstream numbers(line);
        numbers >> a >> b;
        cout << a + b << endl;
    }
    return EXIT_SUCCESS;
}

不定行数,每行不定数量的数字(空格分隔),读取并求和

#include <iostream>
#include <sstream>

using namespace std;

int main(){
    string line;
    while(getline(cin, line, '\n')){
        stringstream numbers(line);
        int sum = 0, tmp;
        while(numbers >> tmp){
            sum += tmp;
        }
        cout << sum << endl;
    }
    return EXIT_SUCCESS;
}

不定行数,每行不定数量的字符串(逗号分隔),读取并排序输出

输入

a,c,bb
f,dddd
nowcoder

输出

a,bb,c
dddd,f
nowcoder

代码

#include<iostream>
#include<sstream>
#include<vector>
#include<algorithm>
using namespace std;

void parseLine(string line){
    stringstream items(line);
    vector<string> words;
    string word;
    while(getline(items, word, ',')){
        words.push_back(word);
    }
    sort(words.begin(), words.end());
    for(int i = 0; i < words.size(); i++){
        cout << words[i];
        if(i == words.size() - 1){
            cout << '\n';
        }else {
            cout << ',';
        }
    }
}

int main(){
    string line;
    while(getline(cin, line, '\n')){
        parseLine(line);
    }
    return EXIT_SUCCESS;
}

各种排序算法

快速排序

int partition(vector<int> &vi, int low, int up) {
	int pivot = vi[up];
	int i = low-1;
	for (int j = low; j < up; j++) {
		if(vi[j] <= pivot) {
			i++;
			swap(vi[i], vi[j]);
		}
	}
	swap(vi[i+1], vi[up]);
	return i+1;
}

void quickSort(vector<int> &vi, int low, int up) {
	if(low < up) {
		int mid = partition(vi, low, up);
		//Watch out! The mid position is on the right place, so we don't need to consider it again.
		//That's why below is mid-1, not mid! Otherwise it will occur overflow error!!!
		quickSort(vi, low, mid-1);
		quickSort(vi, mid+1, up);
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值