一、内存管理: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<<"\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()成员函数。

C++C++ 指针(二)--c++ 指针(二)--c++的更多相关文章

  1. 转: 浅谈C/C++中的指针和数组(二)

    转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ...

  2. C++实现离散余弦变换(参数为二维指针)

    C++实现离散余弦变换(参数为二维指针) 写在前面 到目前为止已经阅读了相当一部分的网格水印等方面的论文了,但是论文的实现进度还没有更上,这个月准备挑选一些较为经典的论文,将其中的算法实现.在实现论文 ...

  3. c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配

    一 数组的结构:顺序存储,看谭浩强中的图,牢记 1.数组名指代一种数据结构:数组 现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的 ...

  4. C语言里的指针探析——type *name[] 在函数参数里面,是一个二维指针

    type *name[] 在函数参数里面声明和不在函数里面声明其实不一样. type *name[] 如果在函数参数里声明,则name 是一个二维指针,并不是一个指针数组,而如果不在函数参数里声明,则 ...

  5. 通过数组初始化链表的两种方法:指向指针的引用node *&tail和指向指针的指针(二维指针)node **tail

    面试高频题:单链表的逆置操作/链表逆序相关文章 点击打开 void init_node(node *tail,char *init_array) 这样声明函数是不正确的,函数的原意是通过数组初始化链表 ...

  6. 二维指针*(void **)的研究(uC/OS-II案例) 《转载》

    uC/OS-II内存管理函数内最难理解的部分就是二维指针,本文以图文并茂的方式对二维指针进行了详细分析与讲解.看完本文,相信对C里面指针的概念又会有进一步的认识. 一.OSMemCreate( ) 函 ...

  7. C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

    原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | I ...

  8. C/C++——二维数组与指针、指针数组、数组指针(行指针)、二级指针的用法

    本文转载自:https://blog.csdn.net/qq_33573235/article/details/79530792 1. 二维数组和指针 要用指针处理二维数组,首先要解决从存储的角度对二 ...

  9. c/c++指针详解(二)

    指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占 ...

  10. C 二维指针难点详解。

    关于   指向二维数组的指针. int  a[2][3]; int *p; int (*p_1)[3]; 可以用p_1 = a ,但是不能用p = a : 因为此时数组a的数据类型是  int (* ...

随机推荐

  1. c++(vs上)与g++(linux下)对于++操作的汇编代码解读

    先来看一个代码,估计很多同学都碰到过其中的某一个. #include <stdio.h> #include <iostream> using namespace std; in ...

  2. 笔试——JAVA相关

    1. String 和 StringBuffer 的区别(转自http://pengcqu.iteye.com/blog/487538) Java笔试题经常考到“String和StringBuffer ...

  3. ORACLE CentOS5.6安装

    1 准备 CentOS 5.6企业版 oracle11g fs 安装.安装环境为vmware虚拟机.另外,本安装文档非常简洁,但关键步骤都指出来了,其他的都是默认选择,遇到不知该如何选择的操作或者问题 ...

  4. LinuxShell脚本攻略--第三章 以文件之名

    生成任意大小的文件文件权限.所有权和粘滞位创建不可修改文件生成空白文件查找符号链接及其指向目标head 与 tail只列出目录的其他方法在命令行中用 pushd 和 popd 快速定位(cd -)统计 ...

  5. 深入理解JVM虚拟机-2垃圾收集器

    这里讨论的收集器基于JDK 1.7 Update 14之后的HotSpot虚拟机. 如果两个收集器之间存在连线,说明可以搭配使用.虚拟机所处的区域,则表示它是属于新生代收集器还是年老代收集器.在这里我 ...

  6. c语言数据结构:01背包问题-------动态规划

    两天的时间都在学习动态规划:小作业(01背包问题:) 数据结构老师布置的这个小作业还真是让人伤头脑,自己实在想不出来了便去网上寻找讲解,看到一篇不错的文章: http://www.cnblogs.co ...

  7. Maximal Rectangle [LeetCode]

    Problem Description: Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle co ...

  8. input覆盖select实现select可写可选择

    1.有时需要一个select选择框,但是对select选择框希望是既可以选择也可以进行输入.下边的代码就是在select选择框上放了一个input框,覆盖在select上面.实现伪装的select效果 ...

  9. GPOR

    [tengzhenzhen15@lu01 gpor]$ for ((i=0; i<=19; i++)) do ./gpor -S 0.4 X4058_300_gpor/mytask_train. ...

  10. [转]网络时间的那些事及 ntpq 详解

    Gentoo(也许其他发行版也是?)中 "ntpq -p" 的 man page 只有简短的描述:“打印出该服务器已知的节点列表和它们的状态概要信息.” 我还没见到关于这个命令的说 ...