0%

任务、线程、进程三者关系

任务是一个抽象的概念,即指软件完成的一个活动;而线程则是完成任务所需的动作;进程则指的是完成此动作所需资源的统称;关于三者的关系,有一个形象的比喻:

  • 任务 = 送货
  • 线程 = 开送货车
  • 系统调度 = 决定合适开哪部送货车
  • 进程 = 道路 + 加油站 + 送货车 + 修车厂
阅读全文 »

编译器是如何实现const关键字功能的

const用于声明变量

const定义的变量只有类型为整数或枚举,且以常量表达式初始化时,在其它地方使用该变量的地方才会被以常量替换。其他情况下它只是一个const限定的变量。但它们都分配了内存地址,把它们统称为常量。

阅读全文 »

关于智能指针的demo,参见C++ primer 12.1

什么是智能指针

智能指针是使用RAII手法对裸指针进行的一个面向对象封装,即在构造函数中初始化资源地址,在析构函数中释放资源。智能指针保证当资源应当被释放的时候一定会释放它,这是利用了栈上的对象出作用域时自动析构这个特点。

阅读全文 »

这篇文章是leetcode刷题系列的第2部分——链表,链表的大部分题目难度都不大。leetcode上链表部分的题目也就40道左右,基本上都做了,这里就把有代表性的题目发出来,共计24道。每道题都给出了注释,有的题目还给出了另一种思路和解法。

leetcode刷题系列其它文章组织如下:

1. 数组

2. 链表

3. 字符串

4. 二叉树

5. 队列和栈

6. 动态规划

7. 数据结构设计

8. 刷题小知识点

阅读全文 »

13. 重载类本身的operator new/delete

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using namespace std;
struct A
{
A()
{
cout << "A() : this:" << this << endl;
}
~A()
{
cout << "~A(): this: " << this << endl;
}

// 这个函数写不写 static 都会被编译器做成 static
static void* operator new(size_t len)
{
return malloc(len);
}

static void operator delete(void* ptr, size_t len)
{
return free(ptr);
}
};

int main()
{
// 调用 A::operator new 版本
A* a = new A();

// 调用全局的 operator new, 如果想调用 A 的版本, 则需显式调用 A::operator new()
void* b = operator new(sizeof(A));


A* c = ::new A(); // 调用全局的 operator new
void* d = ::new A(); // 调用全局的 operator new

delete a; // 先调用 A 的析构函数, 再调用 A 的 operator delete
delete b; // 直接调用了全局的 operator delete
::delete c;
::delete d;
}
阅读全文 »

7. 构造和析构的直接调用方式

通过指针不可以直接调用构造函数,但可以直接调用析构函数。可以通过placement new来直接调用构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct A
{
int a;
int b;
A(int _a, int _b) : a(_a), b(_b) {}
};

int main()
{
A* tmp_a = new A(2, 8);
// tmp->A::A(2, 8); // error! cannot call constructor 'A::A' directly
tmp_a->~A(); // 可以的

// 虽然调用了析构函数, 但事实上 tmp_a 的空间并没有释放
// 因为没有 free 掉, 那块内存还在, 值没有被重写
// 所以可以访问 通过 tmp_a 访问原对象的值
// 如果是 delete tmp_a; 就不能访问
// 因为 delete 调用完析构函数之后, 还调用了 free 函数释放那块内存

cout << tmp_a->a << endl; // 所有这里访问的值看似没有变化
}
阅读全文 »