posts - 183,  comments - 10,  trackbacks - 0

几个面试题的小分析

面试题 100 - 20 最长公共子串
求两个字符串的最长公共子串,不需要连续
根据当前的两个字符 a[i] b[j]
m[i][j]
= max(m[i - 1][j], m[i][j - 1], m[i - 1][j - 1] + k)
if (a[i] = b[j]) k = 1
else k = 0

m[LenA][LenB]

记录路径,根据 max 去哪个值,记录 m 矩阵的走势,是向右、向下还是向右下
求路径的时候,利用辅助矩阵 t[][] 记录的走势状态,递归求出具体的最长公共子串。

面试题 100 - 30 异常安全的复制
一般函数指针成员的类对象,对 operator = 进行重载
在重载的函数体内,有可能造成重新分配内存失败,造成了异常,原来的内存空间已经被释放掉了,无法恢复之前的状态。例如:
T& T::operator = (const T& rhs)
{
 if (this != &rhs)
 {
  delete [] pdata;
  pdata = new Type[];
  copy(...);
 }
 return *this;
}

这种情况下,可能 new 失败造成异常,但是 pdate 指向的内存已经被释放。

为了异常安全
采用临时多一份的策略
第一种方法是,使用一个临时指针,给这个指针分配块内存,然后删除原来的内存,将这个临时指针赋值给本对象中的指针成员。
T& T::operator = (const T& rhs)
{
 if (this != &rhs)
 {
  Type * temp = new Type[];
  copy(...);
  delete [] pdata;
  pdata = temp;
 }
 return *this;
}

第二种方法也是用临时多一份的策略,使用一个临时本类型的对象,利用拷贝构造函数,然后交换临时对象与本对象。
T& T::operator = (const T& rhs)
{
 if (this != &rhs)
 {
  T temp(rhs);
  swap(*this, temp);
 }
 return *this;
}

这里交换的是 *this 和 temp 的指针的值,而不是指针成员指向的内存内容,也就是说是做的对象的位交换。
这种有了一个临时对象,可以不用做自赋值的检测。即便是自赋值,也不会造成原数据的丢失。可以写成:
T& T::operator = (const T& rhs)
{
 T temp(rhs);
 swap(*this, temp);
 return *this;
}

上面的第一种做法,也可以不做自赋值检测。

最上面的非异常安全的做法是
1
0
1
当 0 过后,可能在产生 1 的时候异常,就无法恢复了。
临时多一份的策略是
1
2
1
即便在产生 2 的过程中发生了异常,仍然有一个,所以是异常安全的。
两个发生异常的阶段分别是
0->1
1->2
关键要看异常前的情况,如果异常前就保证有效,则即使发生了异常也没有问题,即是异常安全的。

http://www.cppblog.com/jake1036/archive/2011/05/20/146689.html
http://www.cppblog.com/jake1036/archive/2011/05/20/146816.html

posted on 2011-07-23 21:09 unixfy 阅读(69) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理