前一个是机器视觉组,另外一个组(数据存储)也想面一下,就重新从1面开始了
例如:服务器架构、如何实现多个玩家数据同步、很多玩家同时登陆会怎么样
回答了一些游戏服务器架构的知识,合服原理以及玩家排队机制
Session和Token机制原理上差不多,都是用户身份验证的一种识别手段,它们都有过期时间的限制,但两者又有一些不同的地方。
1、Session是存放在服务器端的,可以保存在:内存、数据库、NoSQL中。它采用空间换时间的策略来进行身份识别,若Session没有持久化落地存储,一旦服务器重启,Session数据会丢失。
2、Token是放在客户端存储的,采用了时间换空间策略,它也是无状态的,所以在分布式环境中应用广泛。
单例模式、抽象工厂方法,策略模式、桥接器模式、装饰器模式、代理模式
我说构造函数使用私有,然后每次创建时,都去检测一下,如果有这个私有变量,就返回私有变量,如果没有,就不返回这个私有变量
其实正确答案应该是静态指针
策略模式更趋向于多选1
装饰器模式应该是执行某个函数前,要先去执行某个前序函数……
上面这个如果写成静态类就可以了。
NULL有二义性,可以是空指针,也可以是int类型的0,
void func()
和 int func()
重载时,NULL会调用int func()
select和epoll
我没有答出来。
答案参考
什么要用父类指针指向子类对象呢?这根本不需要声明为虚函数啊,直接定义一个子类对象,或是用子类指针指向子类对象,再来调用Show函数,即使不用声明为虚函数,也能调用我们派生后重写的Show函数啊。
虽然这样说,但是实际开发过程中不是这样的,当我们使用一些类库、框架的时候,这些类库、框架是事先就写好的。我们在使用的时候不能直接修改类库的源码,我们只能派生类库中的类来覆盖一些成员函数以实现我们的功能,但这些成员函数有的是由
框架调用的。这种情况下,用虚函数是很好的办法。
在面向过程的C语言中,在需要框架、类库回调我们自定义的函数的时候,往往是传入一个函数指针,让框架回调。
在面向对象的C++中,为了实现同样的目的,框架往往准备好了什么也不干的虚函数,由我们派生后重写这个虚函数,来实现我们的自定义功能。随后,框会调用这个虚函数。效果如同面向过程语言中的回调。
1.栈里面的,例如局部变量等等
2.堆里面的,例如新分配的动态分配的内存
3.一些静态变量,会一直全局存在
vector,set,map,string,list,stack,queue
#include //包含string
#include
using namespace std;
int main(int argc, char* argv[]) {
string ss, s;
ss = "1234567";
s = ss;//用=号直接把ss的值1234567赋给s
ss = "1";
cout << s << endl;
return 0;
}
请问s输出什么?这里s输出的还是1234567
是深拷贝
如果在vector迭代过程中,进行了删除操作,会怎么样
迭代器会失效,但是可以获取新的有效的下一个迭代器
没有 = =
会出现异常结果,操作时需要加锁
如果是 各自线程操作各自的链表不会有问题,不然需要同步
我没有做出来,贴一下后来的实现。。。。。
eg:
[2 3]
1 2 3 4 6
1 4 3 2 6
若有更清晰思路请不吝赐教。
#include
#include
using namespace std;
struct LinkNode {
LinkNode* pNext;
int val;
};
LinkNode* GetMaxAPre(LinkNode* pHead, int a) {
LinkNode* pre = pHead;
while (pHead && pHead->pNext)
{
if (pHead->pNext->val<a)
{
pre = pHead;
}
else {
return pre;
}
pHead = pHead->pNext;
pre = pre->pNext;
}
return pre;
}
LinkNode* GetMinBPre(LinkNode* pHead, int b) {
LinkNode* pre = pHead;
while (pHead && pHead->pNext)
{
if (pHead->pNext->val <= b)
{
pre = pHead;
}
else {
return pre;
}
pHead = pHead->pNext;
pre = pre->pNext;
}
return pre;
}
LinkNode* ReverseList(LinkNode* pHead,LinkNode* tail) {
LinkNode* pReverseHead = nullptr; //当前需要连接的头
LinkNode* pNode = pHead;
LinkNode* pPrev = nullptr;
while (pNode != tail)
{
LinkNode* pNext = pNode->pNext;
if (pNext == tail)
{
// 是空,到了最后一个节点了
pReverseHead = pNode;
}
pNode->pNext = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReverseHead;
}
LinkNode* ReverseListA2B(LinkNode* pHead, int a, int b) {
LinkNode* preA = GetMaxAPre(pHead, a);
LinkNode* newTail = preA->pNext;
LinkNode* B = GetMinBPre(preA, b);
LinkNode* BNext;
if (B==nullptr)
{
BNext = nullptr;
}
else {
BNext = B->pNext;
}
if (preA==nullptr )
{
return nullptr;
}
LinkNode* newhead;
if (pHead->val>=a)
{
newhead = ReverseList(pHead, BNext);
preA->pNext = BNext;
return newhead;
}
else {
newhead = ReverseList(preA->pNext, BNext);
}
preA->pNext = newhead;
newTail->pNext = BNext;
return pHead;
}
void testcase(const string caseName, vector<int> data,int a,int b) {
cout << caseName<<" : \n";
LinkNode* pHead = new LinkNode();
pHead->pNext = nullptr;
pHead->val = data[0];
LinkNode* p = pHead;
for (int i = 1; i < data.size(); i++)
{
LinkNode* newNode = new LinkNode();
newNode->pNext = nullptr;
newNode->val = data[i];
p->pNext = newNode;
p = p->pNext;
}
p = pHead;
while (p != nullptr)
{
if (p && p->pNext != nullptr)
{
cout << p->val << " ->";
}
else {
cout << p->val << endl;
}
p = p->pNext;
}
p = ReverseListA2B(pHead, a, b);
while (p != nullptr)
{
if (p && p->pNext != nullptr)
{
cout << p->val << " ->";
}
else {
cout << p->val << endl;
}
p = p->pNext;;
}
cout << endl;
}
int main()
{
vector<int> data{ 0,1,3,4,5,7,9,10 };
testcase("case1", data,1,5); //0 ->5 ->4 ->3 ->1 ->7 ->9 ->10
testcase("case2", data,0,9); //9 ->7 ->5 ->4 ->3 ->1 ->0 ->10
testcase("case3", data,1,10);// 0 ->10 ->9 ->7 ->5 ->4 ->3 ->1
testcase("case4", data,0,10);// 10 ->9 ->7 ->5 ->4 ->3 ->1 ->0
testcase("case5", data, -5, 20);//10 ->9 ->7 ->5 ->4 ->3 ->1 ->0
testcase("case6", data, 1, 20);//0 ->10 ->9 ->7 ->5 ->4 ->3 ->1
testcase("case7", data, 6, 9);//0 ->1 ->3 ->4 ->5 ->9 ->7 ->10
testcase("case8", data, 5, 8);//0 ->1 ->3 ->4 ->7 ->5 ->9 ->10
return 0;
}