需要搞明白的几个问题:
1、3次握手和4次挥手
2、TCP与UDP的区别
3、如果TCP连接出现问题该如何排查,说明排查的思路
连接断开或者出错,会返回一个错误码,errorNo 最后一次系统调用返回的错误码,来看错误的类型。
4、三元组算法问题
5、查询linux系统中的cup和内存占用率
如果查到具体是哪一个进程占用的比较多,你会怎么做?
如何能够降低程序的cpu或者内存的占用率
看是网络程序占用的还是业务逻辑计算功能占用的
如果是网络连接程序,你把网络断了,它还占用那么大,那么网络程序写的有问题
如果是逻辑计算功能占用,我把它的所有数据输入都去掉,如果它还占用那么大,那么业务逻辑计算程序就写的有问题。
6、什么时候使用多线程,什么时候使用多进程
7、单例模式在什么情况下使用,有什么好处
8、对于临界资源的访问有哪几种控制方式
9、什么是原子操作
10、有没有使用过线程池?
explict关键字
//std::atomic_int atomic_int_;//原子
//std::atomic_bool atomic_bool_;
//std::shared_ptr<type_A> ptr_a = std::make_shared<type_A>();
//std::shared_ptr<type_B> ptr_a = std::make_shared<type_B>();
学习ros系统如何使用?
变化是复用的天敌!
面向对象设计最大的优势在于:抵御变化
重新认识面向对象:
理解格力变化:从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小。
各司其职:从微观层面来看,面向对象的方式更强调各个类的责任,由于需求变化导致的新增类型不应该影响原来类型的实现——所谓各司其职
对象是什么?
从语言实现层面来看,对象封装了代码和数据
从规格层面讲,对象是一系列可被使用的公共接口
从概念层面讲,对象是某种拥有责任的抽象。
依赖倒置原则
高层模块(稳定)不应该依赖于底层模块(变化),二者都依赖于抽象(稳定)
抽象(稳定)不应该依赖于实现细节(变化),实现(变化)细节应该依赖于抽象(稳定)
开发封闭原则(OCP)
对扩展开放,对更改封闭。(优先添加代码,而不是修改原来的代码)
类模块应该是可扩展的,但是不可修改。
单一责任原则
一个类应该仅有一个引起变化它的原因。
变化的方向隐含着类的责任。
里氏替换原则
子类必须能够替换他们的基类
继承表达类型抽象
接口隔离原则
不应该强迫客户程序依赖它们不用的方法。
接口应该小而完备
优先使用对象组合,而不是类继承
类继承通常为“白箱复用”,对象组合通常为“黑箱复用”
继承在某种程度上破坏了封装性,子类父类耦合度高
而对象组合则只要求被组合的对象具有良好的定义接口,耦合度低。
封装变化点:(一侧变化,一侧稳定)
使用封装来创建对象之间的分界层,让设计者可以在分界层一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
针对接口编程,而不是针对实现编程
不将变量类型声明为某个特定的具体类,而是声明为某个接口。
客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
减少系统中各部分的依赖关系,从而实现“高内聚低耦合”的类型设计方案。
接口标准化
template method
从目的来看:
创建型模式:将对象的部分创建工作延迟到子类或其他对象,从而应对需求变化为对象创建时ju
面向对象设计模式是“好的面向对象设计”所谓面向对象设计,指那些可以满足“应对变化”,提高复用的设计
现代软件设计特征是“需求的频繁变化”。设计模式的要点是“寻找变化点,然后在变化点处应用设计模式”从而来更好的应对
需求的变化,什么时候什么地点应用设计模式。比 设计模式本身,更为重要。
设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一步到位的设计模式。
敏捷开发实际提倡的Refactoring to Patterns是目前普遍公认的最好的使用设计模式的方法
代码重构关键技法:
静态 -> 动态
早绑定 -> 晚绑定
继承 -> 组合
编译时依赖 -> 运行时依赖
紧耦合 -> 松耦合
组件协作模式
现代软件专业 第一个结果是“框架与应用程序划分”,“组件协作,模式通过晚期绑定”,
来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。
典型模式:
Template Method
Strategy
Observe/Event
定义定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。
Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override重写)该算法的某些特定步骤 。
对象性能模式
面向对象很好地解决抽象的问题,但是必不可免地要付出一些代价,对于通常情况来讲,面向对象的成本大都可以忽略不计,
但是某些情况,面向对象所带来的的成本必须谨慎处理。
经典模式Singletion
怎么样利用面向对象技术实现一些松耦合的设计。
面向对象需要付出一些代价比如说抽象会有虚函数,内存的消耗
使用动机:
在软件系统中,经常有一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保他们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
这应该是是类设计者的责任,而不是使用者的责任。
class Singleton
{
private:
Singleton();
Singleton(const Singleton& other);//单例模式的构造函数和拷贝构造函数是私有的
public:
static Singleton* getInstance();
static Singleton* m_instance;
};
Singleton* Singleton::m_instance = nullptr;
//线程非安全版本
Singleton* Singleton::getInstance()
{
if(m_instance == nullptr)
{
m_instance = new Singleton();
}
return m_instance;
}
//线程安全版本,但是锁代价比较高。
Singleton* Singleton::getInstance()
{
mutex_1.lock();
if(m_instance == nullptr)
{
m_instance = new Singleton();
}
mutex_1.unlock();
return m_instance;
}
//双重检查,但由于内存读写reorder不安全 存在问题
Singleton* Singleton::getInstance()
{
if(m_instance == nullptr) //双重检查
{
mutex_1.lock();
if(m_instance == nullptr)
{
m_instance = new Singleton();
}
mutex_1.unlock();
}
return m_instance;
}
一定是先分配内存,在执行构造器,在进行赋值
//c++11版本之后的跨平台(volatile)
std::atomic<Singleton*> Singleton::m_instance;//声明一个原子对象
std::mutex Singleton::m_mutex;
Singleton* Singleton::getInstance()
{
Singleton* tmp= m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);//获取内存fence
if(tmp == nullptr)
{
std::lock_guard<std::mutex> lock(m_mutex);
tmp = m_instance.load(std::memory_order_relaxed);
if(tmp == nullptr)
{
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);//释放内存fence
m_instance.store(tmp,std::memory_order_relaxed);
}
}
return tmp;
}
保证一个类仅有一个实例,并提供一个该类的全局访问点。
子问题要满足的性质:
1 子问题的范围更小,且子问题个数有限。
2.最优子结构:原问题的目标值(最大/最小/计数),一定是由子问题的目标值转移而来。
3、无后效性:子问题的目标值求解仅局限于子问题的规模,与由那个母状态转移而来无关。
动态规划解题过程
1、定义问题状态:定义问题的状态,已经目标值
2、考虑状态转移:考虑当前状态做出的选择,得到当前状态转移成的子状态,问题规模得到减小。
3、解决子问题:解决规模更小的子问题,并通过子问题的结果更新答案。定义最小的子问题的初始值。
递归求解
int dp(int i,int j)
{
if(i == n && j == n) return w[i][j];
int ret =0;
if(i+1<=n) ret = max(ret,dp(i+1,j));
if(j+1<=m) ret = max(ret,dp(i,j+1));
return ret+w[i][j];
}
字符串面试题的特点
1、广泛性
字符串可以看做字符类型的数组。
与数组排序、查找、调整有关。
很多其它类型的面试题可以看做字符串的面试题。
需要掌握的几个概念:
1、回文
2、字串(连续)
3、子序列(不连续)
4、前缀树(Trie树)
5、后缀树和后缀数组
6、匹配
7、字典序
字符串的操作
1、与数组有关的操作:增删改查
2、字符的替换
3、字符串的旋转
字符串题目的常见类型
1、规则判断
判断字符串是否符合正数规则
判断字符串是否符合小规则
判断字符串是否符合回文规则
2、数字运算
int 和long类型表达整数范围有限所以经常用字符串实现大整数,与大整数相关的加减操作,需要模拟笔算的过程
3、数组的操作相关
数组有关的调整
ListNode* reverse(ListNode* head)
{
ListNode* pre =nullptr;
auto p1=head;
while(p1)
{
auto next = p1->next;
p1->next = pre;
pre = p1;
pre =next;
}
return p1;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)