https://www.cnblogs.com/jiayayao/p/6246468.html
C++语言相关:
(1) 虚函数(多态)的内部实现(C++虚函数实现多态原理(转载))
(2) 智能指针用过哪些?shared_ptr和unique_ptr用的时候需要注意什么?shared_ptr的实现原理是什么? (智能指针shared_ptr的用法、智能指针unique_ptr的用法)
(3) 特化和泛化(算法的泛化过程(摘自《STL源码剖析》)
(4) 为什么不能在构造函数中调用虚函数?
当实例化一个派生类对象时,首先进行基类部分的构造,然后再进行派生类部分的构造。当在构造基类部分时,派生类还没被完全创建,从某种意义上讲此时它只是个基类对象。所以在构造函数中调用虚函数,执行的是基类的虚函数,而非派生类的虚函数。
STL:
(1) vector、list、set、map内部实现以及异同,迭代器插入删除后vector、list、set、map的迭代器是否会失效?
(2) STL除了序列式容器和关联式容器,还有哪些值得学习的?
TCP/IP:
(1) TCP、UDP异同;
(2) TCP、UDP发送一段字符串,其中的发送过程有什么区别?本人理解:TCP有滑动窗口,流量控制,超时重传等机制。
数据结构:
(1) 链表的逆置(又称反转);
(2) 链表有无环的检测,两个链表相交有无可能?相交的形态是什么样的?如何确定相交点?
(3) 如何求出数组中最小(或者最大)的k个数(least k问题)?
(4) 如何求出树中两个结点的最低公共祖先?
本人理解:以上要点必须从根本上明白,理解,不能有糊涂的地方,因为面试官往往会由浅入深的提问,当你不明白一点后,面试官就无需再往下问了,直接确定你的水平了。
2016-12-03 17:19 by jiayayao, 2048 阅读, 0 评论, 收藏, 编辑
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法:
std::unique_ptrmyPtr(new T); std::unique_ptr myOtherPtr = myPtr; // error
但是unique_ptr允许通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,注意,这时它本身就不再拥有原来指针的所有权了。相比于auto_ptr而言,unique_ptr是显示的转移,而不是莫名其妙的报废,因为auto_ptr调用拷贝构造函数后,原来的对象就失效了。
std::unique_ptrmyPtr(new T); std::unique_ptr myOtherPtr = std::move(myPtr); // ok
对于一般的程序使用std::unique_ptr就够了,如果是多线程方面,可能存在共同使用的问题,可以使用std::shared_ptr,注意不要引起循环引用。
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer)。
智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈上的变量自动被销毁,智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。
C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使用时需添加头文件
shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引用计数是安全的,但是对象的读取需要加锁。
可以通过构造函数、std::make_shared
#include "stdafx.h" #include#include #include using namespace std; class Person { public: Person(int v) { value = v; std::cout << "Cons" < p1(new Person(1));// Person(1)的引用计数为1 std::shared_ptr p2 = std::make_shared (2); p1.reset(new Person(3));// 首先生成新对象,然后引用计数减1,引用计数为0,故析构Person(1) // 最后将新对象的指针交给智能指针 std::shared_ptr p3 = p1;//现在p1和p3同时指向Person(3),Person(3)的引用计数为2 p1.reset();//Person(3)的引用计数为1 p3.reset();//Person(3)的引用计数为0,析构Person(3) return 0; }
注意,不能将一个原始指针直接赋值给一个智能指针,如下所示,原因是一个是类,一个是指针。
std::shared_ptrp4 = new int(1);// error
reset()包含两个操作。当智能指针中有值的时候,调用reset()会使引用计数减1.当调用reset(new xxx())重新赋值时,智能指针首先是生成新对象,然后将就对象的引用计数减1(当然,如果发现引用计数为0时,则析构旧对象),然后将新对象的指针交给智能指针保管。
std::shared_ptrp4(new int(5)); int *pInt = p4.get();
智能指针可以指定删除器,当智能指针的引用计数为0时,自动调用指定的删除器来释放内存。std::shared_ptr可以指定删除器的一个原因是其默认删除器不支持数组对象,这一点需要注意。
2. 使用shared_ptr需要注意的问题
但凡一些高级的用法,使用时都有不少陷阱。
int *p5 = new int; std::shared_ptrp6(p5); std::shared_ptr p7(p5);// logic error
function(shared_ptr(new int), g());
struct AStruct; struct BStruct; struct AStruct { std::shared_ptrbPtr; ~AStruct() { cout << "AStruct is deleted!"< APtr; ~BStruct() { cout << "BStruct is deleted!" << endl; } }; void TestLoopReference() { std::shared_ptr ap(new AStruct); std::shared_ptr bp(new BStruct); ap->bPtr = bp; bp->APtr = ap; }
2016-12-06 21:30 by jiayayao, 20016 阅读, 0 评论, 收藏, 编辑
std::function是可调用对象的包装器,它最重要的功能是实现延时调用:
#include "stdafx.h" #include// std::cout #include // std::function void func(void) { std::cout << __FUNCTION__ << std::endl; } class Foo { public: static int foo_func(int a) { std::cout << __FUNCTION__ << "(" << a << ") ->: "; return a; } }; class Bar { public: int operator() (int a) { std::cout << __FUNCTION__ << "(" << a << ") ->: "; return a; } }; int main() { // 绑定普通函数 std::function fr1 = func; fr1(); // 绑定类的静态成员函数 std::function fr2 = Foo::foo_func; std::cout << fr2(100) << std::endl; // 绑定仿函数 Bar bar; fr2 = bar; std::cout << fr2(200) << std::endl; return 0; }
由上边代码定义std::function
std::bind用来将可调用对象与其参数一起进行绑定。绑定后可以使用std::function进行保存,并延迟到我们需要的时候调用:
(1) 将可调用对象与其参数绑定成一个仿函数;
(2) 可绑定部分参数。
在绑定部分参数的时候,通过使用std::placeholders来决定空位参数将会是调用发生时的第几个参数。
#include "stdafx.h" #include// std::cout #include // std::function class A { public: int i_ = 0; // C++11允许非静态(non-static)数据成员在其声明处(在其所属类内部)进行初始化 void output(int x, int y) { std::cout << x << "" << y << std::endl; } }; int main() { A a; // 绑定成员函数,保存为仿函数 std::function fr = std::bind(&A::output, &a, std::placeholders::_1, std::placeholders::_2); // 调用成员函数 fr(1, 2); // 绑定成员变量 std::function fr2 = std::bind(&A::i_, &a); fr2() = 100;// 对成员变量进行赋值 std::cout << a.i_ << std::endl; return 0; }
2015年03月12日 14:33:59 oiooooio 阅读数:4572 标签: c++ boost 多线程 condition_variable 更多
个人分类: boost C++
这篇文章介绍boost::condition_variable的使用。
主要是在多线程的情况下,一般来说boost::condition_variable是用来进行多线程同步的,下面的代码主要测试了notify_one和notify_all的使用。
调用notify_one的时候,启用一个线程。
调用notify_all的时候,激活所有的线程。
当频繁调用notify_one的时候,并不会一直调用唯一的一个线程(在多个线程的情况下),他会激活其他线程,所以优先使用notify_one。
当数据量小于线程数量的时候,如果调用notify_all则会造成其他线程的空运行。
在结尾,附上测试结果。
// ThreadTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "boost/thread.hpp"
#include "boost/thread/condition_variable.hpp"
#include "boost/thread/mutex.hpp"
#include
#include
#include
boost::condition_variable _g_cv;
boost::mutex _g_cv_mutex;
bool _g_is_quit = false;
void ThreadFunc_1()
{
boost::mutex::scoped_lock lock(_g_cv_mutex);
while (!_g_is_quit)
{
_g_cv.wait(lock);
printf("ThreadFunc_1.\n");
// Sleep(10);
}
}
void ThreadFunc_2()
{
boost::mutex::scoped_lock lock(_g_cv_mutex);
while (!_g_is_quit)
{
_g_cv.wait(lock);
printf("ThreadFunc_2.\n");
// Sleep(10);
}
}
void ThreadFunc_3()
{
boost::mutex::scoped_lock lock(_g_cv_mutex);
while (!_g_is_quit)
{
_g_cv.wait(lock);
printf("ThreadFunc_3.\n");
// Sleep(10);
}
}
void ThreadFunc_4()
{
boost::mutex::scoped_lock lock(_g_cv_mutex);
while (!_g_is_quit)
{
_g_cv.wait(lock);
printf("ThreadFunc_4.\n");
// Sleep(10);
}
}
void ThreadControl()
{
#define THREADCOUNT 4
typedef void(*FUNC)();
FUNC threadArray[4] = { ThreadFunc_1, ThreadFunc_2, ThreadFunc_3, ThreadFunc_4 };
for (size_t i = 0; i < THREADCOUNT; i++)
{
boost::thread th(threadArray[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
ThreadControl();
using namespace std;
int value = 0;
while (true)
{
printf("enter 1 to notify one thread.\n");
printf("enter 2 to notify thread one by one.\n");
printf("enter 3 to notify all threads.\n");
printf("enter <-1> to quit.\n");
cin >> value;
switch (value)
{
case -1:
_g_is_quit = true;
break;
case 1:
_g_cv.notify_one();
break;
case 2:
for (size_t i = 0; i < THREADCOUNT; i++)
{
_g_cv.notify_one();
}
break;
case 3:
_g_cv.notify_all();
break;
default:
printf("enter again.\n");
break;
}
if (_g_is_quit){
break;
}
}
system("pause");
return 0;
}
测试结果:
--------------------------------
enter 1 to notify one thread.
enter 2 to notify thread one by one.
enter 3 to notify all threads.
enter <-1> to quit.
1
ThreadFunc_3.
2
ThreadFunc_2.
ThreadFunc_1.
ThreadFunc_4.
ThreadFunc_3.
4
enter again.
3
ThreadFunc_2.
ThreadFunc_1.
ThreadFunc_3.
ThreadFunc_4.