0%

在Windows平台,如果不指定bom头的话,是不清楚当前是什么编码格式的,如果我们在代码中使用了中文,系统根本不知道是utf-8 还是unicode-16,而对Linux来说,默认就是utf-8,所以写中文没关系。

现在VS已经可以支持utf-8 without BOM的源码编译了,VS2015 update2之后就支持附加编译选项/utf-8,支持直接输出中文。 /utf-8 (Set Source and Executable character sets to UTF-8)

看到这道题目的第一反应,HashMap,但100亿真的太多了,我不可能在内存中建立一个这个大的HashMap。

这里面需要的操作是

  1. 计算所有文件的hash(还要解决可能出现的哈希冲突)
  2. 内存中要保存一个几百G的哈希表

查找的时候因为是哈希,所以不需要遍历匹配,所以这块消耗不大。

但内存就否决了方案。

一个优化思路是 计算出hash之后%1000,这样可以分成1000个文件夹,这次每次处理其中一个文件夹就好。

但这里也要问题

  1. 如何保证尽量均为分布到1000个文件夹?很难,尽量选用合适的哈希算法。
  2. IO操作大,因为计算哈希之后要先保存下来,再%1000。

还有一个思路,就是外部排序,然后逐个比较,但外部排序100亿个,O(NlogN),而且也不能一次加载到内存中。

从知乎一个回答上看可以用布隆filter,而这又是redis里的概念,所以

1
mapreduce redis是怎么实现的呢?
Read more »

server code

import socket  

if __name__ == '__main__':
    mySocket = socket.create_server(('10.4.204.21', 2000), reuse_port=False)
    while True:
        pass

client code

import socket
if __name__ == '__main__':
    i = 0
    while True:
        mySocket = socket.create_connection(('10.4.204.21', 2000))
        if mySocket is None:
            print("create client connect failed")
            break
        else:
            print("create client connection succeed")
            i = i + 1
            print('current connection count ', i)  

可以创建连接,但存在几个现象

  1. 输出的connection count 是 129,用netstat -nat | grep -i “2000” | wc -l查看连接数是131,不匹配
  2. 最大连接数理论上受资源限制,ulimit -n能够得到系统设置的tcp最大连接上限是1024,这也远远大于131
  3. create_connection最终是timeout,为什么会timeout,是资源不足了吗?
  4. client进程关掉后,大量的tcp连接仍然没有断掉,要好好了解下TCP状态图。

参考资料

《C++ Concurrency In Action》
《Concurrency With Modern CPP》

并发和并行的概念

在一般的理念中,并发是指 多个thread 请求同一个CPU资源,需要来回切换context;并行是指 每个thread 跑在单独的CPU核上。

在我的工作实践和理解中, 并行是指充分利用CPU多核优势,将代码分解成可以同时运行的模块,当然这里可以同时运行,并不意味着线程间完全没有交互或者耦合,实际工作中我遇到的基本上线程间还是要访问共享内存的,很少遇到那种[0,10e8]相加这种可以完全没有耦合的情况。

并行可以分成两种:

  1. 数据并行
    数据并行是指 可以将数据切分,然后每个部分同时执行相同的逻辑,最终合并结果就可以了。 这是非常完美符合并行概念的。
  2. 业务并行
    业务并行,就是将业务切分,每个线程执行其中一个业务,但每个业务中数据是全程参与的,比如业务分为A B C D,raw_data 进入A, 出来data1 进入B,出来data2 进入C, 出来data3 进入D。 当然这里的raw_data必须是流式的,否则不如单线程 顺序处理所有业务。
Read more »

1
2
3
4
5
6
7
8
9
10
11
12
class Test{
public:
Test(){cout << "explicit constructor with no argument" << endl;}
//Test(Test t){cout << "copy constructor" <<endl;} //1
Test(const Test& t){cout <<"copy constructor" << endl;} //2
Test& operator=(const Test& t){
cout << "operator=(const Test& t)" <<endl;
} //3
Test& operator=(Test t){
cout << "operator=(Test t)" <<endl;
}//4
}

为什么拷贝构造函数不能写成1的形式,必须写成2 的形式?

Read more »

在开发过程中,我们会把自己的数据做一些定义,在程序中表示是数据结构,在本地保存成文件时,就要在文件中定义格式。

那么数据以什么样的形式组织比较好呢?

首先,要明确需求,也就是我们关注的点有哪些?

  • 当前数据集的特点
  • 有没有好的第三方库(稳定,bug少,支持特性多,漏洞少,接口友好)
  • 效率(内存等,不同使用场景下也许不同库存在不同,比如A库在某些场景下优于B,B在某些场景下优于A)

参考资料

A Comparison Of Serialization Formats

在面试或者被面试过程中收集的面试题目,不仅仅与C++相关,还有数据结构和算法,系统等等。


C++

_如何让两个shared_ptr指向同一个实例_

enable_shared_from_memory

今天听面试人说的,以前真没考虑过

只在堆或者栈上创建对象

只在堆上 : operator new()=delete
只在栈上 : private ~base();

static成员变量不能在类内部初始化吗

Case 1

1
2
3
4
static const int  m_iCount = 100; //OK
static const float m_fCount = 1.0f; //error
const int m_iCount = 100; //OK
const float m_fCount = 1.f; //OK

Case 2

1
2
3
4
5
6
7
8
9
10
11
12
13
class base{
public:
base(){cout<<"base construct"<<endl;}
private:
static base m_bObject;
}

int main(){

return 0;
}

output : 空

对m_bObject没有进行类外初始化,但好像也没有调用base的构造函数。

Case 3

1
2
3
4
5
6
7
8
9
10
11
12
13
class base{
public:
base(){cout<<"base construct"<<endl;}
private:
static base m_bObject;
}
base m_bObject;//约等于base m_object = base()
int main(){

return 0;
}

output : base construct

对m_bObject没有进行类外初始化,但好像也没有调用base的构造函数,难道static成员可以不同初始化,除非要使用?

Case 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class base{
public:
base(i){cout<<"base construct"<<endl;}
static base& getInstance(){
m_bObject = base(100)
}
private:
static base m_bObject;
}
base m_bObject;//约等于base m_object = base()
int main(){

return 0;
}

output : error: no matching function for call to ‘base::base()’
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
class base{
public:
base(){cout<<"base construct no param";}
//base(int i){std::cout<<"base construct"<<std::endl;}
static void print(){
std::cout << "test" << std::endl;
}
static void Init(){
static base temp;
m_bObject = temp;//这是类内初始化吗?还是 简单的赋值?
return;
}
public:
static base m_bObject;
};

int main()
{
//base::m_bObject::print(); //error
base::m_bObject.print();//虽然没有初始化,但并不妨碍调用static方法
base::print();
//static base b = base::m_bObject; //undefined reference to `base::m_bObject' 因为此时静态变量没有初始化(分配内存)
b.print();
return 0;
}

这里有两个问题

  • 为初始化的静态成员变量

从上面可以总结得出

  • static变量在未使用之前可以不用初始化
  • static成员变量不会默认初始化(如果不在类外初始化的话)
  • static成员类外初始化

题目

A string S of lowercase English letters is given. We want to partition this string into as many parts as possible so that each letter appears in at most one part, and return a list of integers representing the size of these parts.

Example 1:

Input: S = "ababcbacadefegdehijhklij"
Output: [9,7,8]
Explanation:
The partition is "ababcbaca", "defegde", "hijhklij".
This is a partition so that each letter appears in at most one part.
A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.

Note:

  • S will have length in range [1, 500].
  • S will consist of lowercase English letters (‘a’ to ‘z’) only.
Read more »

在Python的数据类型中,根据是否可改变,分为mutable与immutable。

那么跟C/C++相比,所谓的不可修改是什么意思?

  • 不能进行单个元素的赋值操作
  • 整体的赋值操作,相当于把变量名绑定了一个新的内存区域

下面我们针对tuple来写几个例子。

不能进行单个元素的赋值操作

a = (1, 2)  
a[0] = 2 #error

上面这句话会报 TypeError: ‘tuple’ object does not support item assignment.

对变量进行整体赋值

1
2
3
4
5
6
a = (1, 2)  
id(a) #140036094436208
a = -2, -1 # right (-2, -1)
id(a) #140036072923616
a += (-1, 4) # right (-2, -1, -1, 4)
id(a) # 140036094653072

上面的例子中,我们可以整体赋值,甚至可以用+=,那为什么=不能用,+=可以了。

先拿a = (-2, -1)来说,(-2, -1)相当于生成一个临时对象,绑定到a上。

同样+=相当于 a = a + (-1, 4),a + (-1, 4)组成新的临时对象绑定到a上。

通过id(a)我们可以看到内存的变化(这不是真正的内存地址,但可以看做与内存一致的一个概念)

也就是说,Python所谓的immutable,是说对象目前所绑定的id所指向的内容上不可修改,如果id改了,那么内容自然是可以被修改的。

修改shape会改变对象的内容或者地址吗

我们上面修改了变量的shape,此时变量的内容是没有改变的,我们打印id(a)的值是没有变化的。

1 多线程操作的基本原理

开发语言与系统架构无关,在学习使用C++的时候我们就接触过多线程编程,后面随着处理器多核的出现,有了并行编程,这两个还存在着很大的区别。

说一下我所理解的多线程编程

  1. 存在可以独立执行的Task
  2. Task之间的依赖关系是流式的(或者可以转变为流式)

举个人脸检测的例子

graph LR;
  视频流-->| 检测 |人脸信息;
  人脸信息-->| 后处理 |处理过的人脸信息;
  处理过的人脸信息-->| 显示 |上层回调;

在实际的操作中,我们可以把所有需要处理的视频流保存下来,然后传递给算法引擎,然后得到所有的人脸信息,然后对每一帧的人脸信息进行统一处理,然后再一帧帧返回结果。但这样做效率很低。
我们可以试着这么做,开一个线程A,用于获取视频帧;再开一个线程B,用于算法检测;再开一个线程C,用于回调显示。
这样做的好处是,我拿到一帧视频,放到buffer里(这里甚至可以设定双buffer)。

Multiple buffering

vsync