![](https://img-blog.csdnimg.cn/20201014180756757.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
linux c++基础
文章平均质量分 81
five丶
上海大学软工研究生,cpp后端方向
展开
-
c++编译过程
前言c++是一种编译型语言,在运行之前需要先经过编译器编译,虽然编译器由不同的厂家实现,但是他们需要遵守共同的规范,本文就介绍下c++的编译过程。编译的四个阶段先展示下本文实验用到的代码://main.cpp#include <stdio.h>int main(){ printf ("hello, world"); return 0;}预处理阶段预处理阶段主要处理带“#”号的文件,如#include 或#define等信息,对于include的头文件,预处理原创 2021-06-07 15:52:58 · 458 阅读 · 0 评论 -
设计模式(二):工厂模式
前言工厂模式提供了一种创建对象的最佳方式,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。工厂模式分为简单工厂模式、工厂方法模式和抽象工厂模式,c++工厂模式主要利用了多态的特性,有关多态的内容可以参考c++多态。简单工厂模式简单工厂模式包括三个组件:工厂类:用于创建一个指定具体实例对象。具体产品类:工厂模式创建的对象。抽象产品类:具体产品继承的父类或实现的接口。可以通过一个实例来了解简单工厂模式,假设我们需要通过工厂模式生产衣服,工厂类定义为cl原创 2021-06-06 13:24:51 · 138 阅读 · 0 评论 -
虚拟地址空间(二)
前言在我最开始写博客的时候,第一篇就介绍了虚拟地址空间,但当时受限于自己的水平,并且很多内容当时还没有介绍,所以当时写的比较简单,这篇文章算是还愿了吧。/proc/{pid}/mapslinux的根目录下有很多目录,比如/etc通常是存放参数文件的,/bin通常存放二进制的可执行程序,/lib通常存放库文件,/include存放头文件,/proc存放的则是进程相关的文件。对每个正在运行的文件,/proc下都有一个文件名为该进程pid号的文件夹,例如有一个pid为10086的进程正在运行,那么就存在/p原创 2021-06-06 00:38:21 · 155 阅读 · 0 评论 -
快速排序及其优化
快排的原理快排是综合性能最好的算法,也凭借优秀的性能成为常用的排序算法。快排基于分治的策略,每次选择一个基准值,将数组分为小于基准值和大于基准值两部分,然后对基准左右两侧的数组递归调用这个过程,直至找到所有元素的位置。上面的图片展示了快排的基本过程,但问题是如何找到基准值的位置?最简单的想法是遍历所有元素,但这样就已经排好序了,失去了快排的意义。快排使用两端逼近的思路来找到基准值的位置,相关代码可以这样组织:vector<int> nums//待排序数组int pivot; //基原创 2021-06-04 22:11:29 · 1126 阅读 · 1 评论 -
死锁条件、避免、检测和解除
什么是死锁?如果一个进程集合中的每个进程都在等待只能由此集合中的其他进程才能引发的事件,而无限期陷入僵持的局面称为死锁,例如下面的模型:此时进程A和进程B就永远处于这个状态,称进程A和进程B处于死锁状态。上述的概念换成线程也同样适用,为叙述简洁,这里就使用进程来叙述。死锁条件死锁的产生必须满足四个条件:资源互斥条件:使用资源必须是独占式地,资源本身不可分割,同一资源在某时刻至多只能被一个进程使用;请求和保持条件:进程在请求资源时,不释放目前占有的资源;不可剥夺条件:已经被某进程获取的资源在原创 2021-06-03 23:27:35 · 573 阅读 · 0 评论 -
select使用实例
select函数是多路复用的一种,本文我们给出一个select的通信实例,看下select的代码如何组织,先上代码:#include <unistd.h>#include <iostream>#include <string>#include <sys/socket.h>#include <errno.h>#include <cstring>#include <netinet/in.h>#include &l原创 2021-06-02 00:28:31 · 653 阅读 · 3 评论 -
STL(八):关联式容器
前言关联式容器与序列式容器不同,元素插入关联式容器后,插入位置是由容器采用一定的算法计算的,与插入的时间无关。本文介绍STL中哈系表、集合和map等关联式容器。哈希表hashtable是SGI STL中的哈希表,标准库中使用unordered_map代替hashtable,但unordered_map也是以hashtable为基础的。哈希表是一种查找操作只需要o(1)时间复杂度的数据结构,哈希表由一串连续的的bucket构成,每个bucket上挂着一个链表,链表中储存的就是用户的数据,哈系表通过散列函原创 2021-05-26 22:25:44 · 150 阅读 · 0 评论 -
不同形态的二叉树
满二叉树对二叉树来说,第i层的节点个数最多为2^(i-1)个,如果二叉树的每一层的节点个数都达到最大值,即叶子节点全部在最后一层,非叶子节点一定有左右孩子,这种二叉树称为满二叉树,下面展示了一棵满二叉树。完全二叉树完全二叉树的判断条件没有满二叉树那么苛刻,完全二叉树要求最下面两层的节点,可以没有孩子节点,也可以仅有一个孩子,但最下层的叶子节点必须都在左侧,比如下面的树:需要注意最下层叶子节点必须在左侧,像下面的树违反了这个规则,不是完全二叉树:二叉搜索树二叉搜索树是一种非常实用的二叉树,对原创 2021-05-26 15:55:46 · 809 阅读 · 0 评论 -
二叉树
前言树形数据结构是应用非常广泛的结构,包括二叉树、平衡二叉树、完全二叉树、红黑树、B树和B+树等,本文先介绍基础的树形结构——二叉树。二叉树二叉树是指节点可以有两个孩子节点的树型结构,其中左边的孩子节点称为左孩子,右边的孩子节点称为右孩子。可以通过下面的结构来描述一个二叉树节点,为了数据结构的完整性,这里把构造方法也加上。struct treeNode{ treeNode *left; treeNode *right; int value;//构造函数 treeNode():value原创 2021-05-26 00:17:58 · 79 阅读 · 0 评论 -
STL(七):heap和priority_queue
前言终于快写完序列式容器了!剩最后两个heap和priority_queue,这篇一起写完,明天要开始关联式容器了。heapheap是STL中的堆数据结构,堆其实是一种完全二叉树,即非叶子节点的左右孩子必不为空的二叉树。堆分为最大堆和最小堆,最大堆的特点就是堆顶的元素必定是所有元素中的最大值,而最小堆的特点就是堆顶元素的值必定是所有元素中的最小值,比如下面的结构就是一个最大堆。STL底层使用vector来储存堆中的元素比如图中的最大堆会被储存为[23, 20, 13, 3, 10, 4],这是由于原创 2021-05-25 21:37:04 · 220 阅读 · 0 评论 -
STL(六):list和slist
前言我们已经介绍了vector和deque容器及其适配器,本文我们介绍STL中的链表——list和forward_list。链表链表是在内存中一种不连续的数据结构,链表的每个元素都是一个节点,节点中包含数据和指向下一个元素的指针,如下图:链表通过指针来寻找下一个元素,因此在内存中可以不连续,这极大地提高了使用内存的灵活性。与链表类似的是双向链表,双向链表包含next和prev两个指针:listSTL的list是一种双向链表数据结构,与vector、deque的实现不同,list也是继承自一个原创 2021-05-25 17:57:10 · 269 阅读 · 0 评论 -
STL(五):deque和stack,queue
前言deque是一种序列式容器,翻译为双端队列,deque实现了常数级别的头尾的插入和删除操作,但代价是deque具有比vector复杂的多的机制。deque的设计deque的类图与vector非常相似,数据结构都是存放在_Deque_base中,deque继承_Deque_base,然后定义一些内嵌类型和成员方法。类图中展示了deque的数据成员主要包括一个指针数组和两个迭代器,这与deque的结构有关,deque维护一个中控器,就是指针数组_M_map,中控器中每个元素指向一个数组,数组中是d原创 2021-05-25 00:43:49 · 281 阅读 · 0 评论 -
STL(四):vector和array
前言STL的容器分为序列式容器和关联式容器,其中序列式容器的特点是每个元素均有特定的位置,这个位置和元素的值无关,下面我们介绍四种序列式容器。vectorvector是一种支持动态扩容的数组,在SGI中,其继承关系如下:这里与GNU的STL稍有不同,GNU中_vector_base包含一个名为_vector_impl的成员,这个成员实现了_M_allocate()和_M_deallocate(),而SGI中可以看到是直接在_Vector_base中实现的。vector默认的allocator会为原创 2021-05-24 15:34:36 · 333 阅读 · 0 评论 -
STL(三):traits
前言在前面的介绍中,我们已经多次接触到traits,traits是一种泛型编程技法,用侯捷老师的话说,traits可以回答算法提出的问题,本文我们就来看看基本的traits技法和STL中的traits。traits原理泛型编程通过传入模板元的方法统一了不同类型的接口,在编译时,类型能够自动推导为传入的类型,这被称为泛化,比如下面的结构:template <typename T>struct A{ bool value = true;};泛化时与传入的参数类型是无关的,无论T的类原创 2021-05-23 23:05:55 · 215 阅读 · 0 评论 -
STL(二):Iterator
前言如果把STL的algorithm包含了各种算法的实现,这些算法必须能对不同的容器和容器的适配器进行操作,比如下面的例子:#include <bits/stdc++.h>using namespace std;int main(){ vector<int> m_vec{1, 3, 2, 4}; deque<int> m_deque{1, 3, 2, 4}; sort(m_vec.begin(), m_vec.end()); so原创 2021-05-23 20:53:01 · 191 阅读 · 0 评论 -
STL(一):allocator
系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:第一章 Python 机器学习入门之pandas的使用提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结两级配置前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,原创 2021-05-22 23:13:47 · 128 阅读 · 0 评论 -
c++内存对齐
为什么需要内存对齐?cpu在存取指令时,以字长为单位进行存取,32位机器的默认字长为4字节,64位机器的默认字长为8字节。cpu每次读u取时,都从对齐字长的整数倍开始读取,而存放数据时,cpu以对齐字长的整数倍进行存放,这要求我们对struct或class内的数据排布提出了要求。假如没有内存对齐,数据被任意存放,cpu读取数据时,cpu需要先取出若干个对齐字长的内存,然后去掉开头和尾部不属于所需数据的字节,最后留下的数据块合并后再存入寄存器。考虑内存对齐的作用,cpu存取数据时可以直接取出若干对齐字节大原创 2021-05-16 23:29:51 · 171 阅读 · 0 评论 -
C++四种类型转换
前言在c语言中,通过下面的代码进行一次类型转换:int a = (int)10.0;这种转换通常称为强转,强转存在几个明显的缺点:强转形式上不易被发现,c语言中有很多类型和括号的组合,几乎随处可见,编码人员一眼扫过通常不易察觉强转。强转可能是不安全的,比如下面的代码中,将父类指针转为子类,从内存模型角度上来说,子类内存比父类多出一块,多出的部分结果是不可预知的。#include <iostream>class base{public: int a = 10;};原创 2021-05-16 16:17:46 · 123 阅读 · 0 评论 -
虚函数的内存模型
前言前面文章中我们讨论了虚函数的内存模型,已经了解了包含虚函数的类是通过虚函数表指针、虚函数表和虚函数指针来找到代码段中的函数,本文我们讨论在各种情况下,类在内存中的布局。无继承关系我们看下面的代码:class base1{public: virtual void foo1(){ std::cout << "call base1 foo1" << std::endl; } virtual void foo2(){ st原创 2021-05-03 12:07:49 · 364 阅读 · 0 评论 -
移动语义和完美转发
前言c++11中引入了左右值的概念,通常认为具名的,可赋值的变量为左值,不具名的,不可赋值的变量为右值。其中对右值提供了两个实用的函数std::move()和std::forword(),分别被称为移动语义和完美转发,本文我们对这两个函数进行讨论,在讨论之前,我们先了解引用折叠。引用折叠c++的编译器按照如下规则进行引用折叠:移动语义std::move()通常被称为剪切操作,但个人认为这样称呼其实不太恰当,因为std::move只是将一个左值转换为右值,并不涉及内存的移动,称为剪切还是有些不恰原创 2021-05-02 22:58:58 · 933 阅读 · 0 评论 -
c++多态及其实现
c++是一门面向对象的语言,具有继承、封装和多态三大特性,本文我们总结一下c++中多态的特性及其实现方法。多态指的是调用同一接口,表现出不同的特性,分为静态多态和动态多态。静态多态指在编译期就能确定其特性的多态,而动态多态需要在运行时确定其特性。静态多态静态多态包括重载和模板两种方式。c++重载是指函数在调用时,即使调用的函数名相同,也可以根据参数列表来确定其调用对象,比如下面的代码中有四个函数,main()函数中的调用,根据参数列表的不同,可以找到对应的函数入口。//函数1void foo(){}原创 2021-05-01 22:09:37 · 2209 阅读 · 0 评论 -
c++11智能指针
前言c++中的指针无疑是c++的精髓,极大地提升了编程的灵活性,但各种奇怪的泄漏问题也接踵而至。内存泄漏是指程序中已经动态分配的堆内存未被释放或者无法释放,通常是由于通过new/new[]分配的对象没有匹配地调用delete/delete[],造成系统内存的浪费,严重时甚至会导致系统崩溃。为了解决这些问题,c++引入了auto_ptr,但由于auto_ptr引入了更多的问题,通常被弃用。所以c++11中引入了三种新的智能指针:shared_ptr、weak_ptr和unique_ptr。智能指针基于原创 2021-05-01 19:15:17 · 152 阅读 · 0 评论 -
inline关键字
inline的原理和用法C++中,inline关键字用来表示被修饰的函数是内联函数,内联函数是一种对编译器的建议,当编译器接受这种建议时,内联函数会在被调用处展开,比如下面的例子中,foo()会在调用处被展开。inline void foo(){ cout << "inline" << endl;}int main(){ foo(); return 0;}当程序进行函数调用的时候,程序需要记录ebp,esp等寄存器的值,还需要构造临时变量来接受原创 2021-05-01 16:00:48 · 229 阅读 · 0 评论 -
Const关键字
Const关键字Const意为常量、常数,在c++中,可以用来修饰变量、指针、类对象和函数,同时c++11还引入了constexpr,本文将对const的用法进行总结,并和constexpr对比。Const的用法const修饰变量或者类对象时,就是使变量或类对象中的成员变量不可修改。const修饰指针通常有这三种写法:const int* p,int* const p,int const * p,三种写法非常相似,博主以前也经常忘记,后来记住了规律:const修饰自己左边的,如果左边没有可以修饰的,原创 2021-04-21 00:47:38 · 94 阅读 · 0 评论 -
static关键字
Static关键字Static名为静止的,静态的,C++中的static关键字可以修饰变量、函数和类的成员或方法,并且分别有不同的作用,这篇文章准备总结下static的用法。Static修饰变量全局变量:static修饰全局变量,表示全局静态变量。未初始化时储存在.bss段,初始化后储存在.data段,全局静态变量必须在程序开始运行时就存在,因此定义全局静态变量的声明必须在main()函数前。Static修饰的全局变量,只能在本文件中访问,即使通过extern外部声明也无法访问其他文件中的静原创 2021-04-20 14:52:07 · 122 阅读 · 0 评论 -
虚拟地址空间(一)
前言准备开始更新博客了,博主是c++后端方向的,目前准备先总结下之前的知识,防止忘记,就先从Linux虚拟地址空间开始吧。一、虚拟地址空间是什么?对于32位的Linux操作系统,每个进程加载时,操作系统都会为进程分配4G的虚拟地址空间,其中包括1G的内核空间和3G的用户空间,如下图。需要说明的是,虚拟地址空间并不是真实存在于内存中的,而是对底层物理地址的封装,不同进程的虚拟地址即使相同,对应的物理地址不一定相同,这与MMU有关,我们将在后面的文章中讨论。二、用户空间和内核空间内核空间和用户空.原创 2021-04-20 11:21:25 · 309 阅读 · 1 评论