C C++ 常被人问的问题分析
正文 - 开始了, 直接扯淡
以下都是自己面试中遇到的常见的问题.如有不妥的地方就当见笑了. 哈哈
1. 谈谈你们服务器的架构吧.
分析:
假如这是第一个问题, 你可以走了. 可能各方面原因他不想要你. 或者其它意外已经有人更适合了.
或者只是为了学一点东西.哈哈.一般面试游戏服务器开发的时候,这方面一定会问的. 关于游戏服务器架构,
需要自己努力积累是硬功夫.没有个100页doc难搞下来.且不同公司架构还是很不一样.
只是为了应对面试,可以参照
MMORPG服务器架构 http://www.blogjava.net/landon/archive/2012/07/14/383092.html
云风的 BLOG http://blog.codingnow.com/
至少可以简单扯一点, 对吧.通常这个问题决定你最终资格,极其重要, 也是咱们干程序的一定要积累的.
2. 有时候也会问,项目组正在开发中问题. 因公司而异.
例如怎么设计跨服对战的业务, 怎么设计一个棋牌的随机排序算法.
分析:
1)对于跨服对战, 当初是个卡牌战斗类, 简单些. 按照老套路
a) 每个服前10名, 特定时间报名
b) 按照服务器id,玩家id 构建一个新服
c) 参照老套路了, 有了新服对战开始了...
2) 对于棋牌的随机算法, 基本都是一个傻大哈方法
// // 简单棋牌随机算法 // chess : 存放棋牌的数组 // len : 棋牌处理长度 // void chess_rand(char chess[], int len) { if (!chess || len < 2) return; for (int i = 0; i < len; ++i) { int j = rand() % len; if (i != j) { char c = chess[i]; chess[i] = chess[j]; chess[j] = c; } } }
具体就是你做过就按照你做过的思路说, 没做过就按照自己思路实诚一点说. 哈哈
3. 用过什么数据, 什么数据库引擎,优化什么的扯个淡.
分析:
一般都是mysql, 问几个简单的sql查询.然后问innodb 和 myisam 区别.
其实现在开发我觉得从C++ 软件开发层面. mysql没有mariadb优势大, 高级层面的优化交给数据库开发者. 业务层开发也就是索引等等.
到这里有时候会细问DB Server 设计. 缓存服务器设计等. 因公司业务不同, 说一说完全可以.
也能扯个半天.
4. 那开始扯除了架构之外最重要的了, 多线程设计了.
分析:
首先一般面试官会这样开头, 啊, 那线程和进程的异同是啥呀?这东西常问, 不管是应届菜鸟还是老油条.
因为面试官多数问自己以前被别人问的, 可以参照知乎上讨论, 基本都理解了, 可以来回扯了.
当然这只是个开头,有时候会让你现场写代码. 那就需要自己回顾 pthread POSIX 那套了. 当然遇到必须手写的话, 说明那个人也是为难你.
你也可以放心了. 后面愉快自然些. 他也许还没你懂得多. 详细的可以理解下面知识.
其实关于线程真实工作中, 实战经验为零. 最扯淡的是, 会说的不一定会写, 会写的难说. 仍然推荐可以看看 云风 的 github,
上面多线程代码不少. 还有就是POSIX 多线程那本书特别经典.很给力.
分享个多个线程顺序循环执行的代码, 哈哈如下:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> // 测试线程数量 #define _INT_THS (3) struct threadarg { pthread_t tids[_INT_THS]; sem_t sids[_INT_THS]; }; // 简单运行函数 static void * _run(void * arg) { int i = -1, j = -1; struct threadarg * ths = arg; pthread_t tid = pthread_self(); pthread_detach(tid); // 确定这是第几个线程 while (++i < _INT_THS) if (pthread_equal(tid, ths->tids[i])) break; // 循环个特定遍数就结束吧 while (++j < _INT_THS) { // 第 i 个线程, 等待 第 i - 1 个线程, 输出 'A' + i sem_wait(ths->sids + (i - 1 + _INT_THS) % _INT_THS); putchar('A' + i); // 第 i 个线程, 激活 第 i 个信号量 sem_post(ths->sids + i); } return NULL; } // // 写个测试线程信号量代码 // 开启 _INT_THS 个线程, 顺序打印数据 A->B->C->...->A->B->.... // void test_pthread_sem(void) { // 开始初始化了 int i, j; struct threadarg targ; // 先初始化信号量,后初始化线程 for (i = 0; i < _INT_THS; ++i) { // 0 : 表示局部信号量当前可用; 0 : 当前信号量值为0 if (sem_init(targ.sids + i, 0, 0) < 0) goto __for_exit; } // 开启线程 for (j = 0; j < _INT_THS; ++j) { // 开启三个线程 if (pthread_create(targ.tids + j, NULL, _run, &targ) < 0) goto __for_exit; } // 激活第一个线程, 输出 'A' 开头 sem_post(targ.sids + _INT_THS - 1); // 中间等待一些时间吧 getchar(); __for_exit: // 注意的是, 假如信号量释放了, 线程还在跑, 会异常 for (j = 0; j < i; ++j) sem_destroy(targ.sids + j); #ifdef __GNUC__ exit(EXIT_SUCCESS); #endif }
编译指令是
test_pthread_sem.exe:test_pthread_sem.c
gcc -g -Wall --entry=$(basename $@) -nostartfiles -o $@ $^ -lpthread
后面也可以参照下面链接学习一下.
5. 那再一次到语法基础部分了. C++各种语法妖魔来了. 哈哈
存在这样一个情况. 一个函数玩家new了个对象. 但是忘记delete了.直接return了,怎么搞别内存泄漏.
分析:
其实这类C++问题, 在C++最经典的书籍中都有解释. 一般人会回答用智能指针. 这时候面试官和蔼的告诉你不行.
你sb了. 那怎么搞哈哈. 如果做过很简单,没做过就xxx了. 其实这时候面试官希望你自己实现个简单的智能指针. 其实这个
很好搞, 本质就是C++栈上变量在函数返回时候会退栈,执行变量析构函数.其实再扯一点,这种特性本质就是编译器在编译的时候
,帮我们插入了这些构建和清理的代码而以. 一个简单的代码如下:
template<typename T> class AutoPtr { T * _ptr; public: explicit AutoPtr(T * ptr) { _ptr = ptr; } ~AutoPtr(void) { delete _ptr; } T & operator*() { return *_ptr; } T * operator->() { return _ptr; } };
用法也特别简单
class People { }; AutoPtr<People> ptr(new People());
到这里就各种妖魔鬼怪出来. 例如会继续问placement new 的用法. 呵呵, 各种奇葩问题来了.
参照上面资料看的挺有意思.一般而言 placement new 用在指定对象分配上.
#define _INT_XX (108)
char xx[_INT_XX]; T * p = new(xx) T;
当然还有更加奇葩的在构造函数和析构函数中抛出异常. 这种问题面试一问基本上基础部分就接近尾声了. 能扯个30min吧.
说白了, C++ 的 new 和 delete 还是很有搞头的 O(∩_∩)O哈哈~ ┻┳|・ω・)问我?
6. 又是最简单的虚函数了, 必问. 直接搞起吧.
虚函数virtual可以说是C++面向对象的所有. 面试时必问的基础中的基础.(✪ω✪) 让我们来剖析其中的秘密吧.
virutal虚函数围绕本质在于编译器帮我们在类中插入了 __vfptr 变量. 例如下面例子.
以上就是虚函数实现原理.通过汇编好实现.通过纯C++实现有点难搞, 需要记住类型.
7. 那到了STL部分了,也是常有的. 搞一搞吧.
STL是必问的,其实问的都很简单. 多数是看看下面STL代码是够有问题. 奥, 常见的有各种容易的区别.
回答的时候需要抓住迭代器特点. 存储结构特点. 例如只有vector和deque是顺序存储并且支持随机迭代器的.
有的会问怎么删除vector中是偶数的迭代器. 手写代码.
int i = 0; std::vector<int> vs; std::vector<int>::iterator it = vs.begin(); while (it != vs.end()) { if (++i % 2 == 0) it = vs.erase(it); else ++it; }
主要是注意一下迭代器失效的情况.
后面扯扯C++11方面知识. 其实哈哈, 都C++17了, 还11. 说白了高级程序员,
高级的地方不在于功底, 不在于能力, 最重要的是业务熟悉度, 和当前公司的业务匹配度.
8. TCP 和 epoll 出现了. 其实也很简单.
网络这块也是逃不掉的.什么四次分手, 3次握手是必须的.
这里TCP搞完了, 那开始问select, epoll 什么的. 可以了开始考验你api 和 内核的理解了
套路都差不多. 多总结总结, 这里面试官一问能扯个5-10min吧. 毕竟除了老一辈的程序员功底好些.
新的对于这些也只是 --> "编程5min扯淡2h" ! O(∩_∩)O哈哈~ 关于epoll 实际用法可以参照我的下面博文
后记 - 新的开始, 哈哈
以上就是老鸟找工作必问的问题, 深入的扯能够扯好久.... 错误是难免的, 欢迎指正, 共同提高~~~
虚虚实实 http://music.163.com/#/m/song?id=189433&userid=16529894
人生没有重来, 贪婪有何不可 -|- 对不起我的兄弟和我的妹子