zoukankan      html  css  js  c++  java
  • 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;
    }
    1) new格式:
    char* ptr = new char [len+1]
     

    指针

    =

    关键字

    变量的数据类型

    char类型变量的数目(方括号)

             new和malloc:new方法可以返回适当的数据类型的指针;而malloc返回的指针是void类型的指针,必须强制转化才能转化成适当的数据类型指针。
    C中的realloc函数可以改变已分配内存空间的大小。C++中没有这样的函数,只能通过new重新申请一个更大或者更小的空间。
    2) delete格式:delete【】 要删除的指针
    如果new创建的是一个简单的对象,则在删除的时候可不加方括号,如果是数组就必须加括号。
     

    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<<" 姓名排序后:";
        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()成员函数。

  • 相关阅读:
    数据结构----字典及部分知识总结(2018/10/18)
    数据结构----链表的逆置及链表逆置和删除极小值
    Python自学知识点----Day03
    Python自学知识点----Day02
    Python自学知识点----Day01
    课堂笔记及知识点----树(2018/10/24(pm))
    课堂笔记及知识点----栈和队列(2018/10/24(am))
    数据结构----链表的删除和遍历(2018/10/24)
    数据结构----顺序表的增和遍历(2018/10/23)
    知识点回顾及委托(2018/10/22)
  • 原文地址:https://www.cnblogs.com/zsq1993/p/5962252.html
Copyright © 2011-2022 走看看