C++笔试的一些代码题目
两个线程交替打印0-100的奇数和偶数#includethread #includemutex #includecondition_variable void main() { condition_variable cv; mutex mtx; int x 0, n 0; cout 请输入开始; cin x; cout 请输入结束; cin n; thread t1([, n]() { while (1) { unique_lockmutex lock(mtx); if (x n) break; if(x % 2 0) cv.wait(lock); //奇数 //cv.wait(lock, [x]() { return x % 2 1; }); cout this_thread::get_id() : x endl; x; cv.notify_one(); } }); thread t2([, n]() { while (1) { unique_lockmutex lock(mtx); if (x n) break; if (x % 2 ! 0) cv.wait(lock); //偶数 //cv.wait(lock, [x]() { return x % 2 0; }); cout this_thread::get_id() : x endl; x; cv.notify_one(); } }); t1.join(); t2.join(); } //C也支持条件变量不是线程安全的所以要配合锁使用 //题目两个线程交替打印一个线程打印奇数一个打印偶数 //condition_variable::wait 当前进程会进行阻塞直到被唤醒和linux一样在阻塞之前会进行解锁防止死锁问题然后唤醒后重新申请锁 //文档中的 wait_for和wait_until表示等待的时间notify_one和notify_all表示唤醒一个线程和唤醒所有线程 //如何做到t1和t2不管谁抢到锁都保证t1先运行t2阻塞 -- t1不等待t2有等待这样t1获得了锁t2就等着t2获得了锁但是wait释放锁t1获得锁 //如何防止一个线程不断申请锁释放锁不断运行 t1打印的时候释放锁并且通知t2t2重新获得锁但是t1没停下来又等待了t1又获得了锁 -- t1, if(x%2 0) cv.wait(lock); t2,if (x % 2 ! 0) cv.wait(lock); //为什么要防止一个线程连续打印 -- 假设t1先获取到锁t2后获取到锁t2就阻塞在锁上面 -- t1打印奇数xx变成偶数 -- t1 notift唤醒但是没有线程wait因为t1有锁t2没有锁所以在阻塞等待 -- t1解锁t1时间片到了切出去了 // -- t2获取到锁打印notify但是没有线程等待t2再出作用域解锁 -- t2的时间片充裕会比t1先获得锁所以如果没有条件控制就会导致t2连续打印判断机器大小端#include iostream using namespace std; int main() { int a 1; if (*(char*)a 1) //先取出a的地址将其转化为char*后此时再解引用就只会读取地址指向位置的第一个字节的数据 cout 小端模式 endl; else cout 大端模式 endl; return 0; }模拟实现memset#includeiostream #includemutex using namespace std; void* my_memcpy(void* p1, void* p2, unsigned int count) { if (!p1 || !p2) return NULL; char* pD (char*)p1; char* pS (char*)p2; if (pD pS || pD (pS count)) while (count--) *pD *pS; else //处理内存重叠 { pD (char*)p1 count - 1; pS (char*)p2 count - 1; while (count--) *pD-- *pS--; } return p1; } int main() { char tmpBuf[128] 111111222222333333444444; char destBuf[128] { 0 }; std::cout 1 (char*)my_memcpy(destBuf, tmpBuf, 10) std::endl; std::cout 2 destBuf std::endl; std::cout 3 (char*)my_memcpy(tmpBuf 5, tmpBuf, 10) std::endl; std::cout 4 tmpBuf std::endl; return 0; }手撕智能指针auto_ptrnamespace p1 { templateclass T class auto_ptr { public: auto_ptr(T* ptr nullptr) :_ptr(ptr) {} auto_ptr(auto_ptrTp) { _ptr p._ptr; p._ptr nullptr; } ~auto_ptr() { if (_ptr ! nullptr) { cout delete: _ptr endl; _ptr nullptr; } } auto_ptr operator(auto_ptrT ap) { if (this ! ap) { delete _ptr; //释放自己管理的资源 _ptr ap._ptr; //接管ap对象的资源 ap._ptr nullptr; //管理权转移后ap被置空 } return *this; } //可以像指针一样使用 T operator*() { return *_ptr; } T* operator-() { return _ptr; } private: T* _ptr; }; } int main1() { p1::auto_ptrint p1(new int(1)); p1::auto_ptrint p2(p1); return 0; }unique_ptrnamespace p2 { templateclass T class unique_ptr { unique_ptr(T* ptr nullptr) :_ptr(ptr) {} ~unique_ptr() { if (_ptr ! nullptr) { delete _ptr; cout delete: _ptr endl; _ptr nullptr; } } T operator*() { return *_ptr; } T* operator-() { return _ptr; } unique_ptr(unique_ptrT p) delete; //直接禁用拷贝 unique_ptr operator(unique_ptrT p) delete; private: T* _ptr; }; }shared_ptrnamespace p3 { templateclass T class shared_ptr { public: shared_ptr(T* ptr nullptr) :_ptr(ptr) , _pcount(new int(1)) {} shared_ptr(shared_ptrT sp) :_ptr(sp._ptr) , _pcount(sp._pcount) //拷贝时获取对方的计数并 { (*_pcount); } ~shared_ptr() { if (--(*_pcount) 0) //如果为0代表这是最后一次释放需要delete { if (_ptr ! nullptr) { delete _ptr; _ptr nullptr; cout delete: _ptr endl; } delete _pcount; _pcount nullptr; } } shared_ptr operator(shared_ptrT sp) { if (_ptr ! sp._ptr) //管理同一块空间的对象之间无需进行赋值操作 { if (--(*_pcount) 0) //将管理的资源对应的引用计数-- { delete _ptr; delete _pcount; cout delete: _ptr endl; } _ptr sp._ptr; //与sp对象一同管理它的资源 _pcount sp._pcount; //获取sp对象管理的资源对应的引用计数 (*_pcount); //新增一个对象来管理该资源引用计数 } return *this; } //获取引用计数 int use_count() { return *_pcount; } T operator*() { return *_ptr; } T* operator-() { return _ptr; } private: T* _ptr; //管理的资源 int* _pcount; //管理的资源对应的引用计数 }; }由于计数是建立在堆上的一旦处于多线程环境可能会有线程安全问题下面是线程安全版的shared_ptr:namespace p3_thread_safe { templateclass T class shared_ptr { private: //引用计数 void AddRef() { _pmutex-lock(); (*_pcount); _pmutex-unlock(); } //--引用计数 void ReleaseRef() { _pmutex-lock(); bool flag false; if (--(*_pcount) 0) //将管理的资源对应的引用计数-- { if (_ptr ! nullptr) { cout delete: _ptr endl; delete _ptr; _ptr nullptr; } delete _pcount; _pcount nullptr; flag true; } _pmutex-unlock(); if (flag true) { delete _pmutex; } } public: //RAII shared_ptr(T* ptr nullptr) :_ptr(ptr) , _pcount(new int(1)) , _pmutex(new mutex) { } ~shared_ptr() { ReleaseRef(); } shared_ptr(shared_ptrT sp) :_ptr(sp._ptr) , _pcount(sp._pcount) , _pmutex(sp._pmutex) { AddRef(); } shared_ptr operator(shared_ptrT sp) { if (_ptr ! sp._ptr) //管理同一块空间的对象之间无需进行赋值操作 { ReleaseRef(); //将管理的资源对应的引用计数-- _ptr sp._ptr; //与sp对象一同管理它的资源 _pcount sp._pcount; //获取sp对象管理的资源对应的引用计数 _pmutex sp._pmutex; //获取sp对象管理的资源对应的互斥锁 AddRef(); //新增一个对象来管理该资源引用计数 } return *this; } //获取引用计数 int use_count() { return *_pcount; } //可以像指针一样使用 T operator*() { return *_ptr; } T* operator-() { return _ptr; } private: T* _ptr; //管理的资源 int* _pcount; //管理的资源对应的引用计数 mutex* _pmutex; //管理的资源对应的互斥锁 }; }weak_ptrnamespace p4 { templateclass T class weak_ptr { public: weak_ptr() :_ptr(nullptr) {} weak_ptr(const shared_ptrT sp) :_ptr(sp.get()) {} weak_ptr operator(const shared_ptrT sp) { _ptr sp.get(); return *this; } //可以像指针一样使用 T operator*() { return *_ptr; } T* operator-() { return _ptr; } private: T* _ptr; //管理的资源 }; }