自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(65)
  • 收藏
  • 关注

原创 凸包算法(Convex Hull Algorithm)

凸包定义平面上 N 个点的凸包是包围这 N 个点的最小多边形 应用机器人运动路径规划:找到起点 S 到终点 T 之间的最短路径,而且需要避开一个多边形路障s 和 t 之间的最短路径就是 s 和 t 之间的直线距离,或者凸包中上下折线中的其中之一最远的两点:平面上有 N 个点,希望找到这 N 个点中,距离最远的那一个点对距离最远的那一对点,一定在凸包上属性在凸包上,可以只通过做逆时针转弯而遍历闭凸包以最小的 y 值点 p 为原点,与其他点的连线的极角逐渐增大

2020-09-27 10:08:27 7333 1

原创 乱序算法(shuffling algorithm)

文章目录问题基于排序的shuffling基于交换的shuffling问题shuffling 就是希望打乱一个基本有序的序列,越乱越好比如现在有一个已经排好序的 objects,以下面扑克牌为例:我们希望能够随机的打乱它的顺序,比如得到下面的序列:基于排序的shuffling我们可以为每一个数组中的元素随机的产生一个随机数,然后对随机数进行排序,排序的同时移动相应的数组中的元素,排序完成后,即可以实现数组中的元素乱序:基于交换的shuffling...

2020-09-24 09:27:40 1831

原创 并查集

文章目录1. 动态连接问题2. 解决思路3. 代码实现3.1 Quick Find1. 动态连接问题实际问题Union Find 常用来解决动态连接 (Dynamic connectivity) 问题。在很多实际应用中,都存在动态连接问题,比如:一张图里面的像素点的相关操作网络中的计算机社交网络中的好友关系数学集合中的元素…抽象问题简单来说,动态连接问题可以抽象为如下问题:有若 N 个节点 0,1,…,n-1,希望对它能有如下操作:Union:将两个节点连接在一起Fin

2020-09-12 15:54:52 182

原创 【Effective C++】用成员模板函数接受所有兼容的类型

问题我们知道,指针有一个很好的点,就是能够在类继承层次之间支持隐式转换,derived class 指针能够被隐式转换为 base class 指针,如下面这样:class Top {};class Middle : public Top {};class Bottom : public Middle {};Top* pt1 = new Middle(); //Middle* 被转换为 Top*Top* pt2 = new Bottom(); //Bottom* 被转换为 Top*const

2020-09-07 20:50:09 217

原创 【Effective C++】处理模板化基类中的名称

引例假设现在有这样一个例子:class CompanyA {public: void sendClearText(const std::string& msg); void sendEncryted(const std::string& msg); //...};class CompanyB {public: void sendClearText(const std::string& msg); void sendEncryted(const std::st

2020-08-30 15:46:49 105

原创 【Effective C++】typename 双重含义

含义一:模板声明在 template 的声明式中,可以使用 class 或者 typename,如下:template<class T> class Widget;template<typename T> class Widget;在这里,class 和 typename 没有任何不同,个人倾向于使用 typename,避免与类型声明的 class 混淆。含义二:声明嵌套从属名称类型变量假设现在有这样一个模板函数,传进来一个模板容器,希望打印出容器内的第二个元素:

2020-08-30 12:17:46 160

原创 【操作系统】10. 调度

1. 调度算法First Come First Service (FIFO)如果进程在执行中阻塞,那么在队列中的下一个进程会得到 CPU举例来说,如果现在有三个进程,p1, p2, p3,假设我们事先知道它们的执行时间是 12, 3, 3。按照 FIFO算法:如果它们以 p1, p2, p3 的顺序到达,那么它们的执行顺序就是 p1, p2, p3,整个的平均周转时间 = (12 + (12 + 3) + (12 + 3 + 3)) / 3 = 15;如果它们以 p2, p3, p1 的顺

2020-07-26 15:31:13 192

原创 C++ 虚继承

在 C++ 多继承中,可能会出现 the most derived class 拥有多个 the most based class 的多份相同数据成员。比如说下面这种菱形继承的情况:class A{public: int a;};class B : public A{public: int b;};class C : public A{public: int c;};class D : public B, public C{public: int d;};

2020-06-23 22:34:26 196

原创 【Effective C++】谨慎使用 private 继承

引例:考虑 Person,Student 继承体系,Student 以 private 继承 Person:class Person { //... };class Student : private Person { //... };void eat(const Person& p);void study(const Student& s);void main(){ Person p; Student s; eat(p); eat(s);}这个时候,eat

2020-06-15 11:54:42 285

原创 【Effective C++】对象之间的复合(composition)关系 —— has a 以及 is-implemented-in-terms-of

复合关系当某种类型的对象内含其他种类型的对象时,它们之间便是这种复合关系。比如:class Address { //... };class PhoneNumber { //... };class Person {public: //...private: std::string name; Address address; PhoneNumber voiceNumber; PhoneNumber faxNumber;};在这里例子中,Person 对象就由 std::strin

2020-06-10 16:44:27 343

原创 【Effective C++】不要重新定义继承而来的缺省参数值

现在考虑这样一种继承体系:class Shape{public: enum ShapeColor {Red, Green, Blue}; virtual void draw(ShapeColor color = Red) const = 0; //...};class Rectangle : public Shape{public: virtual void draw(ShapeColor color = Green) const;};class Circle : publi

2020-06-10 16:00:47 155

原创 【C++内存管理】GCC4.9 array_allocator 源码分析

array_allocator 直接就是用 std::array 来做的内存管理。先分配一大块数组,然后客户需要多少内存,就直接从数组中拿去,实现较为简单先看看它的数据成员:array_type* _M_array; size_type _M_used;array_type 就是 std::array 类型,也就是 _M_array 可以看作是一个指向数组的指针。_M_used 就是标定数组中有多少内存块是分配出去了的。allocator 函数源码: pointerall

2020-06-09 20:00:59 346

原创 【C++内存管理】loki::allocator 源码分析

loki 是书籍 《Modern C++ Design》配套发行的一个 C++ 代码库,里面对模板的使用发挥到了极致,对设计模式进行了代码实现。这里是 loki 库的源码。ps. 有空是不是应该把里面的设计模式的代码学习学习, hahahahloki 库里面有两个文件,SmallObj.h 以及 SmallObj.cpp,就是一个内存管理的内,可以单独使用。下面就其源码进行分析。1. 类层次结构SmallObj 文件里面有三个类:Chunk,FixedAllocator 和 SmallObj

2020-06-07 16:12:43 980 1

原创 【Effective C++】virtual function 的替代方案

假设你正在为一个游戏软件中的人物设计一个继承体系。每个人物都有一个血量值,且不同的人物之间血量的变化方式也不一样,基于这样的目的,你可能会想着这样设计一个基类:class GameCharacter{public: virtual int healthValue() const; //返回人物当前的血量 //...};具体的人物类会继承这个 GameCharacter 基类,可以在其中对血量的计算函数 healthValue() 进行重写。在基类中,并没有将 healthValue() 函数

2020-06-06 11:42:45 194

原创 【Effective C++】区分接口继承和实现继承

当你在设计一个 class 的继承体系时,对于基类的成员函数,你可能会希望 Derived class :只继承基类成员函数的接口能够同时继承基类成员函数的接口和实现,但是又希望能够 override能够同时继承基类成员函数的接口和实现,且不允许 override这三种不同的基类成员函数实现方式,实际上就对应了基类成员函数的三种不同形式:pure virtual function,impure virtual function 和 non-virtual function。假设现在有如下的继承

2020-06-05 10:41:56 182

原创 【Effective C++】避免隐藏继承而来的名称

这个主题可能更多的是和作用域有关。先来看看下面这种简单的情形:int x;void func(){ double x; std::cin >> x; //读的是 local double x variable}这里,cin 读取的就是 local 的 x 变量,而不是 global 的 x 变量。因为内层作用域的名称会屏蔽掉外围作用域的名称,即使它们的类型并不相同。那在继承体系下,又是怎样的情形呢?继承体系下的作用域问题现在有下面这种继承结构:class Bas

2020-06-04 12:26:07 217

原创 【Effective C++】将文件之间的编译关系降到最低

C++ 的编译依赖关系如果你对 C++ 的某个实现文件做了修改,你可能会发现,所有与这个类有关的其他项目文件都需要重新编译。这主要归咎于 C++ 并没有把 “将接口与实现分离” 这件事情做得很好。比如说像下面这样:#include<string>#include"date.h"#include"address.h"class Person{ //对外接口public: Person(const std::string& name, const Date& b

2020-06-03 17:39:30 168

原创 【Effective C++】彻底了解 inline 函数

inline 函数有着众多优点:看起来像是函数,使用起来也像是函数,但是又没有函数调用的额外开销比宏好用得多,具体见 这篇文章方便编译器执行语境相关最优化。因为大部分编译器会对那些“不含函数调”用的代码进行优化。所以当你 inline 某个函数,或许编译器就可以对调用它的函数进行语境相关的最优化。当然天下没有白吃的午餐,inline 函数也有它自己的缺点:对 inline 函数的每一次调用,都会用 inline 函数本体进行替换。这样就有可能增加目标代码的大小,甚至会导致额外的换页行为,引起

2020-06-02 15:41:46 342

原创 【C++内存管理】G2.9 std::alloc 源码分析

在 上一篇 中,对 std::alloc 的运行时状态进行了分析,这篇再结合上一篇,深入代码分析。常量定义enum { __ALIGN = 8 }; // block 的间隔enum { __MAX_BYTES = 128 }; // block 的最大 bytesenum { __NFREELISTS = __MAX_BYTES / __ALIGN }; //free-lists 的个数这里它用的是 enum 定

2020-06-01 20:35:59 329

原创 【C++内存管理】G2.9 std::alloc 运行模式

在上一篇里面说到,vs 的标准分配器 std::allocator 并没有做内存管理。gnu的历史版本 2.9 中的标准分配器 std::allocator 也没有做内存管理,但是它提供的 extended allocator 中,std::alloc 就是一个做了内存管理的版本。在 gnu 新版本中,__gnu_cxx::__pool_alloc<_Ty> 就是 G2.9 的 std::alloc 的化身。 下面先分析以下 std::alloc 的运行模式,再下一篇分析具体代码。 不过

2020-05-29 18:11:07 1082 1

原创 【Effective C++】尽量写出“异常安全”的代码

异常安全代码的目标当函数抛出异常时,具有“异常安全”性的代码应该实现以下两点:不泄露任何资源。不破坏数据。 也就是说,系统处于前后一致的状态。比如下面这个代码:class Image;//多线程环境下使用class Menu{private: std::mutex mtx; //互斥器 Image* bgImg; //当前的背景图案 int imgChanges; //图案被改变的次数public: //改变背景图像 void ChangeBackground(st

2020-05-29 11:40:24 287

原创 【C++内存管理】vs2017 标准分配器实现

vs2017 标准库中,std::allocator 的实现如下:template<class _Ty>class allocator{//... void deallocate(_Ty * const _Ptr, const size_t _Count) { // deallocate object at _Ptr // no overflow check on the following multiply; we assume _Allocate did that check

2020-05-27 15:51:10 588

原创 【Effective C++】避免返回 handles 指向对象内部成分

首先抛出结论:不要返回对象私有成员的 handles ,handles 指引用,指针和迭代器。这样可以增强类的封装性,避免可能出现的 const 成员函数不 const (即外部仍然可以通过 const 成员函数修改对象内部私有数据),以及 dangling handles 的问题 (即空指针或空引用)。返回私有成员指针在下面 LeftBottom 和 RightTop 函数中,我们是想要客户端获得 Rectangle 对象的左下角和右上角的点坐标。因为在这两个函数内部,并没有修改对象内部数据,

2020-05-27 11:47:16 295

原创 【C++内存管理】内存管理实例 (三 ) —— static allocator

在上一篇中,利用 Embeded pointer 的概念为某一个类设计出了一个内存管理模块。在掌握这种方法之后,以后只要有哪一个类需要做内存管理,都可以采用那种方法,重载 operator new 和 operator delete 函数。这个时候,我们自然的想到把内存分配的这个模块抽象出来,在其中做统一的处理。这个时候就有了这个 static allocator 的版本。设计一个新的 cla...

2020-05-22 09:59:39 480

原创 【Effective C++】尽量少做转型动作

转型语法转型通常有三种形式:C 风格的转型动作:(T) expression函数风格的转型动作:T( expression )C++ 风格的转型动作,其中又提供了四种操作,各有不同的目的。 C++ 风格的四种转型操作const_cast用来移除对象上的常量性 (const) 或者是易变性 (volatile)static_cast主要用于非多态类型之间的转换用于基本数据类型之间的转换,比如说 int 转换为 char,double 等用于类的继承层次结构中,基类和子类之间指

2020-05-20 09:50:52 162

原创 【Effective C++】考虑写出一个不抛出异常的swap函数

首先抛出结论:下面再来讲讲原因:swap含义及缺省实现swap 函数是用来将两个对象的指彼此赋予对方。在缺省情况下,swap的动作可以由STL中提供的 swap 算法来完成,它的实现也很简单:namespace std{ template<typename T> void swap(T& a, T& b) { T temp(a); a = b; b = temp; }}只要 T 支持拷贝构造和拷贝赋值, 缺省的 swap 就会为你完成置换 T

2020-05-17 10:16:01 280

原创 【C++内存管理】内存管理实例 (二) —— Embeded pointer

在上一篇的内存管理实例中,我们用一个 next 指针将分配的一整块内存中的每个对象大小的内存块链接成链表,客户端需要动态分配对象内存时,直接从链表上获取,减少了不必要的 cookie 内存消耗。但是缺点也很明显,就是增加了每个对象的 next 指针的内存消耗。我们可以看看什么时候会使用到 next 指针:当分配了一大块内存,这一大块内存上的每个对象大小的小内存块需要用 next 指针串在一起,...

2020-04-26 21:03:22 411

原创 【C++内存管理】内存管理实例 (一 ) —— 简单形式

内存管理无外乎希望提高两方面性能:提高运行效率。可以通过减少 malloc 函数调用的次数来提高运行效率。提高空间利用率。减少浪费。每次通过 new 分配的内存块上下两个部分都带有 cookie,记录着这块内存的大小等相关信息。可以通过分配一大块内存池,在将其中分为一小块一小块以供对象实例存放,这样的话,只在这一大块的头尾存在 cookie,中间部分省掉了很多 cookie 的占用内存,提高...

2020-04-18 17:47:19 525 1

原创 【C++内存管理】placement new 重载示例

可以为 operator new 写出多个重载版本,但是每一个版本的第一个参数都必须为 size_t 类型。其余的参数以 new 所指定的 placement arguements 为初值,出现在 new(…) 小括号里面的就是所谓的 placement arguements.比如我们可以继续为 Foo 类型写 operator new 重载:class Foo{public: Foo(...

2020-04-18 15:23:49 713

原创 【C++内存管理】operator new重载示例

可以对 operator new 进行重载,实现自己的内存分配方式和资源释放。下面是示例代码:class Foo{public: Foo() : _id(0) { cout << "default constructor. id = " << _id << endl; } Foo(int i) : _id(i) { cout <&l...

2020-04-18 09:54:02 336

原创 【C++内存管理】new expression

当我们用 new 去动态分配内存时:complex *pc = new complex(1, 2);编译器会为我们转为如下实现:complex *pc;try{ void *mem = operator new(sizeof(complex)); //allocate pc = static_cast<complex*>(mem); //cast pc->c...

2020-04-17 21:42:25 282

原创 【C++内存管理】placement new

placement new 允许我们在已有的内存上调用构造函数创建 object,如下用法://先分配内存char *buf = new char[sizeof(complex) * 3];//在 buf 指针所指的位置调用 complex 的构造函数,complex *pc = new(buf)complex(1, 2);...//释放内存delete[] buf;背后编译器...

2020-04-17 20:02:46 229

原创 【C++内存管理】array new 和 array delete

使用方法使用 new 加 [] 可以为数组分配内存,使用方法如下:Complex *pca = new Complex[3];这样的话,就分配了一块3个 Complex 大小的内存,并且分别调用三次 Complex 的默认构造函数。当不在使用这块内存时,需要搭配 delete[] 使用,它会先三次调用 Complex 的析构函数,然后将这块内存给释放掉:delete[] pca;...

2020-04-17 16:54:36 468

原创 【Effective C++】以独立语句将 new 出来的对象放入到智能指针

首先抛出结论:当你 new 出来一块内存,并且想把他们放入到智能指针当中时,最好使用一条独立语句,否则可能会发生内存泄露。下面再来讲讲原因:考虑有这样一个函数 ProcessWidget:class Widget;int CalPriority();void ProcessWidget(std::shared_ptr<Widget> pw, int priority)...

2020-04-08 11:02:31 244

原创 【Effective C++】operator= 拷贝赋值操作注意事项

首先抛出结论:让 operator= 返回一个 reference to *this要在 operator= 中处理“自我赋值”要在 operator= 中处理“异常”,不可盲目的将当前内存直接删除,防止分配新内存失败让 operator= 返回 reference to *this主要是基于以下两点考虑:1. 减少不必要的拷贝构造函数的调用。可以对比分析一下直接返回对象和返回...

2020-04-06 12:10:17 174

原创 【Effective C++】不要在构造函数和析构函数中调用 virtual 函数

首先结论如标题所示。如果你有一个类的继承体系,用来模拟股票交易市场的买进卖出,并且每一笔交易都需要进行记录,那么可能会有如下的类继承关系:class Transaction {public: Transaction() { //... LogTransaction(); } virtual void LogTransaction() const = 0;};clas...

2020-04-05 12:22:28 164

原创 【Effective C++】不要让异常逃离析构函数

首先先抛出结论:析构函数绝对不要抛出异常。如果在一个析构函数中某个函数可能调用失败,抛出异常,这个析构函数应该捕捉这个异常,然后“吞下”他们,或者结束程序。如果客户端需要对某个操作函数运行期间抛出的异常做出反应,那么这个 class 应该提供一个普通函数接口,而不是在析构函数中自己处理异常。假如有以下的代码片段:class Widget {public: ... ~Widget...

2020-04-05 10:40:30 171

原创 【Effevtive C++】尽量以 const enum inline 替换 #define

以 const 或者 enum 替换 #define 常量定义在 C 代码中,我们可能会用以下宏定义去定义一个常量:#define N 2这种方法只是在预编译的时候进行了字符替换,也就是会将所有 N 出现的地方替换为 2。在预编译之后,程序中将不会再有 N 这个标志。N不是变量,并不占内存单元,容易出错。比如下面这个例子:int n = 2;#define N1 n + n#defi...

2020-04-02 12:54:32 233

原创 C++ 11新特性(一)

【侯捷-C++11新特性-variadic templates】用例void print(){}template<typename T, typename... Types>void print(const T& firstArg, const Types&... args){ std::cout << "variadic params ...

2020-03-13 08:34:27 698

原创 C++ STL源码分析——tuple

【侯捷-SL体系结构内核分析-tuple】tuple也是一个容器,它可以将任意类型的数据组合在一起,形成一个容器对象,它可以用于函数返回多个值。定义对象如下:tuple<int, double, const char*> t1;可以在定义时可以直接初始化,也可以直接赋值:tuple<int, double, const char*> t1(12, 20.5, "z...

2020-03-07 22:00:55 509

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除