C++C++ 指针(二)--c++ 指针(二)--c++
一、内存管理:new和delete
1、new操作符:从操作系统获得内存块,并返回该内存块的首地址。
delete操作符:将new申请的内存返还给操作系统。
开始一个简单的例子:
#include <iostream>#include<cstring>using namespace std;int main(){    char* str="it is a good job!";    int len=strlen(str);    char* ptr=new char[len+1];    strcpy(ptr,str);    //ptr=str;  //错误,这样是ptr和str都指向字符串。这里ptr和str应该指向不同的地址。    cout<<"ptr="<<ptr<<endl;    delete[] ptr;    return 0;} | 
| char* | ptr | = | new | char | [len+1] | 
| 
 指针  | 
 =  | 
 关键字  | 
 变量的数据类型  | 
 char类型变量的数目(方括号)  | 
2.使用new的类
#include<iostream>using namespace std;class String{public:    String(char* s)    {        int len=strlen(s);        str=new char[len+1];        strcpy(str,s);    }    ~String()    {        cout<<"where?"<<endl;        delete[] str;    }    void display()    {        cout<<str<<endl;    }private:    char* str;};int main(){    String str="hello! word!";    str.display();    return 0;   } | 
1)在构造函数中使用new获得内存空间。
2)既然使用new来分配内存空间,因而析构函数也变得很重要。(因为在创建对象的时分配了内存空间,则当这些对象不再需要时就很有必要释放这些空间)。析构函数在对象销毁时自动调用的例程,所以放入delete恰好。
问题:如果一个类的两个对象执行了s1=s2这样的操作(即出现两个对象的指针指向同一个内存地址),而此时一个对象被删除(如含有其中一个对象的调用函数结束后返回时),这样申请的内存地址被收回,这样就导致另一个对象的是一个无效的指针了。
这个错误一定要重视,因为很容易疏忽。怎样才能写一个更聪明的析构函数呢?? 后面揭晓…
二、对象与指针
1、对象指针
有时在程序的编写时并不知道需要创建多少个对象。当出现这中情况时,就可以在程序运行中使用new来穿件对象。这里,new返回的是一个指向未命名对象的指针。
例子:
#include<iostream>using namespace std;class Distance{public:    void getdist();    void showdist();private:    int feet;    float inches;};void Distance::getdist(){    cout<<"Enter the feet:"; cin>>feet;    cout<<"Enter the inches:";cin>>inches;}void Distance::showdist(){    cout<<"The feet:"<<feet<<endl;    cout<<"The inches:"<<inches<<endl;}int main(){    Distance dd;    dd.getdist();    dd.showdist();    Distance* ptr=new Distance; // pointer to Distance,points to new Distance object    ptr->getdist();  //这里如果是点运算符就会出错    ptr->showdist(); //因为点运算符要求它的左运算符是一个变量,而ptr为一个指针。    return 0;} | 
上面标注的地方除了用成员访问运算符(->)表示之外,我们还可以这样(*ptr).getdist(); //ok,but inelegant (圆括号是必须的,因为点运算符的优先级比间接引用运算符要高).
2、对象指针数组
Distance* distptr[100];distptr[j]=new Distance;//*(distptr+j)=new Distance;distptr->getdist();distptr->showdist(); | 
注意:数组表示法distptr[j]等价于指正表示法*(distptr+j),由于是指针数组,上面两种表示的方法的元素还是指针(指向对象的指针)
distptr->getdist(); 表示执行了由数组distptr的第j个元素 所指向的Distance对象的成员函数。
三、链表
链表提供了一种不使用数组但更为灵活的存储系统,每个数据项都是按照需要通过new来获取的,且数据之间是通过指针链接起来的。
单个数据项之间并不需要和数组元素一样在内存中相邻分配,相反他们可以分散到任何地方。
例子:
#include <iostream>using namespace std;struct link{    int data;     //表示对象的单个数据项    link* next;   //指向下一个链接项};class linklist{public:    linklist():first(NULL) {}    void addlist(int d);   //增加链接项    void display();        //显示链接内容private:    link* first;};void linklist::addlist(int d)  //增加链接项{    link* newptr=new link; //创建一个新的link结构类型    newptr->data=d;        //将参数的值传递给结构变量data      newptr->next=first;    //指针next指向first指向的任何地址(在这里是链表头)    first=newptr;          //将指针first指向这个新的链接项}void linklist::display(){    link* nowptr=first;    while (nowptr!=NULL)    {        cout<<nowptr->data<<endl;        nowptr=nowptr->next;  //指针移动到下一个链表的地址    }}int main(){    linklist ll;    ll.addlist(22);    ll.addlist(33);    ll.addlist(44);    ll.display();    return 0;} | 
注意:在使用link结构的时候含有一个指向同类型结构的指针。同样的在类中也可以这么使用:
class sampleclass{    sampleclass* ptr;   //this is fine!    sampleclass obj;    //can't do this!!}; | 
但是这里要特别注意:虽然类中可以包含一个指向同类型对象的一个指针,但不能包含一个同类的对象。
四、指向指针的指针
看个例子:
#include<iostream>#include <string>using namespace std;class person{public:    void SetName()    {        cout<<"Enter name:"; cin>>name;    }    void PrintfName()    {        cout<<name;    }    string GetName()    {        return name;    }private:    string name;};int main(){    void bsort(person**,int);     //排序    person* perptr[100];    int n=0;    char ch;    do    {        *(perptr+n)=new person;        (*(perptr+n))->SetName();        n++;        cout<<"Enter another?";        cin>>ch;    } while (ch=='y');    cout<<"姓名排序前:";    for (int j=0;j<n;j++)    {        perptr[j]->PrintfName();        cout<<" ";    }    bsort(perptr,n);    cout<<"\n姓名排序后:";    for (int j=0;j<n;j++)    {        perptr[j]->PrintfName();        cout<<" ";    }    cout<<endl;    return 0;}void bsort(person** ptr,int n)  //排序{    void order(person**,person**);    int j,k;    for(j=0;j<n-1;j++)        for(k=j+1;k<n;k++)            order(ptr+j,ptr+k);}void order(person** ptr1,person** ptr2)  //比较{    if((*ptr1)->GetName()>(*ptr2)->GetName()))    {        person* tem;        tem=*ptr1;        *ptr1=*ptr2;        *ptr2=tem;    }} | 
1)注意到数据类型person**,表示这些参数被用来传递perptr指针数组的地址。本身perptr数组中存的就是指针,因此指针数组的地址是一个指向指针的指针。
2)因为数组perptr包含的是指针,因而:perptr[j]->PrintfName(); 表示执行perptr数组的j号元素所指向的对象的PrintfName()成员函数。
3)(*ptr1)->GetName();
其中ptr1是一个指向指针的指针,因此(*ptr1)表示指针数组的元素。总体意思就是执行perptr数组的元素(*ptr1)所指向的对象的PrintfName()成员函数。
                    
                
                
            
        
浙公网安备 33010602011771号