关于C++指针

一.
怎样给多维数组动态分配内存

//Allocate:
int **p = new int* [m];
for(int i = 0 ; i < m ; i++)
    p[i] = new int[n];
//Use:
for(int i = 0 ; i < m; i++)
    for(int j = 0 ; j < n ; j++)
        p[i][j] = i * j;
//Free:
for(int i = 0 ; i < m ; i++)
    delete[] p[i];
delete[] p;

 

二.
字符数组V字符串指针:
字符数组如果在函数里声明则在栈上分配内存空间.
char a[1034]="bac" --true,这时可以改变a地址范围内的任一地址所指向的内容.如:a[0]='a'.而a的值一般是不变的,除非重新分配地址.
char a[1034];  a="bac"  --faile 因为"abc"有const char*类型的,而a是char的.
strcpy(a,"abc");    -true

如果声明字符串指针char *a ="abc"常量,当把常量赋给一个指针(a)时,则a是在静态存储空间分配内存,原则上a地址里范围内指向的内容不可以改变.
char *a="abc";   a="bcd" --true 可以改变a的值,但不可以改变这个地址里范围内指向的内容.                                    char *a;  a="abc"; --true
char *a="abc"; a[1]='d';   -false
strcpy(a,"abc")    --false *a的值不可变


char *a=malloc(size); --则a在堆分配空间,相当于char a[size],用free释放内存
char *a=new char(size);  --同上,不过要用delete释放内存
这时strcpy(a,"abc"); a[n]='d';    --true

三.多态:
  
  #include<iostream>  
  using   namespace   std;  
  class   a    
  {  
  public:  
  a()   :   b(1234){}  
  int   b;  
  virtual   int   get()  
  {  
  cout<<"a::get()";  
  return   b;  
  }  
  };  
  class   c   :public   a  
  {  
  public:  
  c()   :   d(2345){}  
  int   d;  
  int   add()  
  {  
  return   d+7;  
  }  
  int   get()  
  {  
  cout<<"c::get()";  
  return   d;  
  }  
  };  
  /*void   fun(a   &www)//第一版本  
  {  
  cout<<www.get()   <<   endl;  
  }*/  
  void   fun(a   www)//第二版本  
  {  
  cout<<www.get()   <<   endl;  
  }  
  int   main()  
  {  
  a   *pa;  
  c   cc;  
  pa=&cc;//很正常  
  cout<<pa->get()<<endl;//调用了c类的函数  
  c*   pc;  
  a   aa;  
  pc=(c*)&aa;//这句强制转换  
  cout<<pc->get()<<endl;//调用了a类的函数  
  cout<<pc->add()<<endl;//此句会出错!?虽然pc是指向a对象,但是他却成功的调用了c中的add();这是为何?  
  fun(cc);//使用第一   版本就调用c,使用第二版本就调用a  
  fun(aa);//使用第一版本就调用a,使用第二版本就调用a  
  return   0;  
  }  
  int   main()中前6行是没有问题的。  
  第7行,pc   =   (c*)   &aa;就是把强行把派生类的指针指向基类的对象,这是危险的操作,但不会发生对象切割,因为这只是修改了一个指针,并没有对类的对象去实施什么破坏性的操作。  
  45:               pc=(c*)&aa;//这句强制转换  
  004016C8       lea                   eax,[ebp-1ch]  
  004016CB       mov                   dword   ptr   [ebp-14h],eax  
  从汇编上看出,它只是把aa对象的地址ebp-1ch放到了pc所占的内存中ebp-14h中,没有动aa对象ebp-1ch附近的内容,所以不会数据丢失。  
  cout<<pc->get()<<endl;凑合着可以运行,因为get本身是a类的一个成员函数,因为它是虚的,所以这里调用的是a类的函数。  
  cout<<pc->add()<<endl;这也凑合着可以运行,因为虽然a类中没有add()函数,但因为c类中的add()不是虚的,所以这里做静态绑定,调用了c类的add()函数。因为add()函数中对一个a类中不存在成员d进行了加7操作,所以就返回了一个无效的数字。可以从输出结果中清楚的看到。  
  004016FD       mov                   ecx,dword   ptr   [ebp-14h]  
  00401700       call                 @ILT+415(c::add)   (004011a4)  
  从汇编上看出,这里没有用虚函数的机制,只是一个静态绑定。  
  如果把add也改成virtual的,这里就会做动态绑定  
  00401704       mov                   ecx,dword   ptr   [ebp-14h]  
  00401707       call                 dword   ptr   [edx+4]  
  结果就更离奇了,您可以自己试试。  
  对于这一点,为什么可以正常调用(但结果不对)非虚的add()函数,可以再参考我在另一个贴中的回复。  
  http://expert.csdn.net/Expert/topic/1414/1414072.xml?temp=.8994867  
  下面解释func:  
  第一版本是传引用,就相当于是传了指针,所以可以实现多态。func(cc)会调用c的get(),func(aa)会调a的get()。  
  004016DF       lea                   ecx,[ebp-1Ch]  
  004016E2       push                 ecx  
  004016E3       call                 @ILT+350(fun)   (00401163)  
  可看出,只用堆栈传了指针,没有挎贝对象。  
  第二版本是传对象,会调挎贝构造函数,这里没有定义,所以就进行了默认的挎贝。因为形参是基类a的,它不知道c又在它身上加了d这个成员,所以它就把一个c的对象挎贝成了a的对象,a中没有的成员d就被切割了。所以func(cc)和func(aa)都只会调a的成员函数get()。这种现象就是所谓的“对象切割”,经过挎贝后,c的对象被切割得只剩下a的部分了。  
  0040172C       call                 @ILT+115(a::a)   (00401078)  
  00401731       call                 @ILT+640(fun)   (00401285)  
  很明显调了a的挎贝构造函数,对象被切割。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值