C++编程语言虽然功能强大,应用方式灵活,但是在实际编程中同样会出现各种各样的错误。在这里我们将会为大家详细介绍一下有关C++指针漂移的解决方法,希望本文介绍的内容可以帮助大家解决问题。
  最近我们在工作中碰到一个奇怪的问题,最后确定是多继承引起的C++指针漂移,跟C++对象模型有关。示意如下:
  class A {...};  class B{...};  class AB : public B, public A {...}  ...  AB *pab = new AB();  A* pa = (A*)pab;  B* pb = (B*)pab; 这时候你发现pa和pb的值是不一样的!它们中有一个跟pab是相等的,而另外一个产生了偏移。如果把AB的声明中A和B的顺序调换一下,则产生偏移的指针也会变为另外一个。
  为了确定这是编译器做了转换的缘故,利用void指针愚弄编译器:
  void *pv = (void*)pab;  pa = (A*)pv; 这时候pa的值倒是跟pab相等了,然而指向了错误的地方。从pab到pa的转换,依赖于路径的选择,让人不是很放心。还不知道把指针放入容器中再取出来,会不会出错。当然,上面使用了强制类型转换,在良好的程序中应该避免。如果只有隐式转换,可以得到正确的结果:
  std::vector<A*> v;  //implicit type conversion  v.insert(v.begin(), pab);  void *pv = v[0];  pa = (A*)pv; 以下程序使用Cygwin/g++b编译通过:
  #include <stdio.h> #include <vector> class A   {  public:  int a;  };  class B   {  public:  int b;  };  class AB : public B, public A   {  public:  int ab;  };  int main(int argc, char **argv)  {  AB *pab = new AB();  pab->ab = 1;  pab->b = 2;  pab->a = 3;  A* pa = (A*)pab;  B* pb = (B*)pab;  printf( "AB: %p\n" \  " A: %p\n" \  " B: %p\n",  pab, pa, pb);  std::vector<A*> v;  //implicit type conversion  v.insert(v.begin(), pab);  void *pv = v[0];  pa = (A*)pv;  printf("pv is %p\npa is %p\npab %s pv\n", pv, pa, (pab == pv) ? "==" : "!=");  printf("A.a is %d\n", pa->a);  //forced type conversion  pv = (void*)pab;  pa = (A*)pv;  printf("Now A.a is %d\n", pa->a);  } 运行结果:
  AB: 0x6b01f0   A: 0x6b01f4   B: 0x6b01f0   pv is 0x6b01f4   pa  C++编程语言中的模板应用是一个比较复杂的应用技术,我们今天就先从C++ kmp算法模板的基本应用开始学习,从而加深我们对这方面知识的认识程度,方便将来的应用,提高编程效率。
  在使用的时候加上这两行代码就行了
  #include < vector>   using namespace std;
  C++ kmp算法模板参数说明
  const T *source 待匹配的字符串
  TL sourceLen 待匹配字符串的长度
  const T *pattern 模式串
  TL 模式串长度
  C++ kmp算法模板代码示例:
  template < class T,class TL>   inline int kmpmatch(const T *source,TL sourceLen,const T *pattern,TL patternLen)
  {   vector< int> next;
  for ( int i = 0; i <  patternLen ; i ++ )   next.push_back(0);   next[0] = -1;   for( int i = 1 ; i <  patternLen ; i ++ )
  {   int j = next[i - 1];
  while ( (pattern != pattern[i + 1])&& (j >= 0))
  {   j = next[j];   }
  if ( pattern == pattern[j + 1])
  {   next = j + 1;   }
  else   {   next = -1;   }   }
  int i = 0;   int j = 0;
  while (( i <  sourceLen ) && ( j <  patternLen ))
  {   if ( source == pattern[j] )
  {   i ++;   j ++;   }   else if ( j == 0 )
  {   i ++;   }   else   {   j = next[j - 1 ] + 1;   }   }
  if ( j >= patternLen )
  {   if ( !next.empty() )
  next.clear();
  return i - patternLen ;
  }
  else
  {   if ( !next.empty() )   next.clear();
  return -1;   }   }
is 0x6b01f4   pab != pv   A.a is 3   Now A.a is 2
KMP起源于字符串的匹配,顾名思义匹配字符就是看2串字符是能匹配上,比如说字符串S=”abcd”字符串T=”abc”,就可以匹配上,返回的是第一个匹配的位置,也就是1。
1、最基本的匹配。从原字符串开始搜索,若出现不能匹配,则从原搜索位置+1继续。这样时间复杂度是很高的。 
                        
 
虽然前4位一样但是第5位不一样,需要从原来的位置+1,再进行匹配。 
                        
 
以此类推,直到匹配为止。
/*检测从主串T的
pos位置开始,是否有和子串S匹配,如果有返回匹配开始位置,如果没有,返回-
1T:主串S:子串tlength:主串长度slength:子串长度
pos:主串开始位置
*/int Index (char T[],char S[],
int tlength,
int slength,
int pos){    
int j=
0,i=
pos;    
while(i<tlength&&j<slength)    {        
if(T
==S[j])        {            i++;            j++;        }        else        {            i=i-j+1;            j=0;        }    }    return j==slength?i-slength:-1;}- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 
2、KMP匹配算法。KMP算法就是改进了不匹配时候返回去从哪个位置开始再进行比较。比如当第一个主串的c与子串中的a不匹配时,下一次的 主串的b和子串的a(第一个)的比较可以通过分析子串的特点直接跳过这次比较。KMP算法就是为了告诉我们,我们应该每当一趟匹配过程中出现比较不等时,我们不需要回溯i指针。而是利用已经得到的“部分匹配”的结果将模式子串想右“滑动”尽可能远的距离,然后继续比较。首先先要统计一下要匹配的字符串中的重复情况,也就是求一个next[]数组。 
                        
 
求出next[]数组后,再进行匹配的时候就会加快速度。举一个求next[]数组的例子: 
                        
下面是一个KMP的实现例子。
#include <vector>#include <string>#include <iostream>using namespace std;
const vector<int> * kmp_next(
string &m){    
static vector<int> next(m.size());    next[
0]=
0;    
int temp;    
for(
int i=
1; i<next.size(); i++)    {        temp=next[i-
1];        
while(m
!=m[temp]&&temp>0)        {            temp=next[temp-1];        }        if(m==m[temp])            next=temp+1;        else next=0;    }    return &next;}bool kmp_search(string text,string m,int &pos){    const vector<int> * next=kmp_next(m);    int tp=0;    int mp=0;    for(tp=0; tp<text.size(); tp++)    {        while(text[tp]!=m[mp]&&mp)            mp=(*next)[mp-1];        if(text[tp]==m[mp])            mp++;        if(mp==m.size())        {            pos=tp-mp+1;            return true;        }    }    if(tp==text.size())        return false;}int main(){    int pos=0;    kmp_search("abcacbc","ca",pos);    cout<<"position = "<<pos+1<<endl;    return 0;}- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 
3、KMP改进算法。KMP算法还是存在着一定的不足,比如S=”AAAABCDE”时候,T=”AAAAAX”这个时候可以求出next[]数组值为:012345,开始时i=5、j=5发现B与A不一致,j=next[5]=4。以此类推发现有多余的判断。由于T串的第2、3、4、5位置的字符和第一个位置的字符是一样的,那么可以用首位的next[1]代替相应的next[j]的值。于是对next[j]改进。 
nextval数组的求解方法是:nextval[1]=0。从第二位开始,若要求nextval,将next的值对应的位的值与i的值进行比较(例如,第i为的值为’b’,next=3,则将i的值’b’与第三位的值进行比较),若相等,nextval=nextval【next】(例,nextval=nextval[3]);若不相等,则nextval=next(例,nextval=next=3)。 
                        
1.第一位的nextval值必定为0,第二位如果与第一位相同则为0,如果不同则为1。 
2.第三位的next值为1,那么将第三位和第一位进行比较,均为a,相同,则,第三位的nextval值为0。 
3.第四位的next值为2,那么将第四位和第二位进行比较,不同,则第四位的nextval值为其next值,为2。 
4.第五位的next值为2,那么将第五位和第二位进行比较,相同,第二位的next值为1,则继续将第二位与第一位进行比较,不同,则第五位的nextval值为第二位的next值,为1。 
5.第六位的next值为3,那么将第六位和第三位进行比较,不同,则第六位的nextval值为其next值,为3。 
6.第七位的next值为1,那么将第七位和第一位进行比较,相同,则第七位的nextval值为0。 
7.第八位的next值为2,那么将第八位和第二位进行比较,不同,则第八位的nextval值为其next值,为2。