zoukankan      html  css  js  c++  java
  • C++的优秀特性4:指针

    (转载请注明原创于潘多拉盒子)

    其实指针不是C++的特性,而是地地道道的C的特性。有人说C++继承了C的指针,实在是败笔,造成内存泄漏云云,纯粹是不懂。可以这么说,如果没有指针,C++会逊色很多,应用的场景也会大大缩小。

    指针是一个变量,这个变量和一个int型的变量没有太大的不同,只是这个变量里存储的是它指向的对象的内存地址。

    指针可以指向任何对象,包括内置类型(int、long、double、float等),对象类型,函数入口,甚至另外一个指针或者可以指向任何类型 。

    涉及指针的操作符包括:定义指针(*)、解引用(*)、取地址(&)、取成员(->)、偏移解引用([]),偏移(+、-)、求偏移(-)。

    先看看几种指针的例子:

    1. 指向int型变量的指针:int* p = new int(0);
    2. 指向对象的指针:Widget* p = new Widget();
    3. 指向函数的指针:int (*p)(int n) = factorial; 这里p是指向已经定义的函数factorial的函数指针。
    4. 指向指针的指针:Widget** pp = &p;
    5. 可以指向任何类型的指针:void* any = NULL; 这里的any是指向任何类型变量的指针。比如any = p; 或是any = pp; 甚至any = &pp; 都是合法的。

    对于#1和#2的情况,大家应该已经比较熟悉,这里就不赘述了。

    对于函数指针,在C语言实现动态方法绑定中非常有用。在C++中,更多的是通过接口虚函数覆盖(override)来代替。在某些兼容C程序动态行为绑定的例子中,可以采用函数指针。

    比如我们可以根据用户输入的命令,定义对应的处理函数:

    typedef bool (*command_process)(int argc, char** argv);
    
    bool start(int argc, char** argv)
    {
        // implementations
    }
    
    bool stop(int argc, char** argv)
    {
        // implementations
    }
    
    bool write(int argc, char** argv)
    {
        // implementations
    }
    
    
    bool read(int argc, char** argv)
    {
        // implementations
    }
    
    // assign processors to names
    std::map<std::string, command_process> processors;
    processors["start"] = start;
    processors["stop"] = stop;
    processors["write"] = write;
    processors["read"] = read;
    
    // use processors to process commands
    std::string command = "start";
    processors[command](argc, argv);  // 调用名称“start”对应的处理函数,实现动态效果
    

      比较有意思的是可以指向任何类型的变量的指针,比如:

    // 为了简单,这些变量全部定义在栈上,其实可以是new出来的
    int n = 256;
    double x = 3.14159265;
    Widget w;
    
    // 定义一个任意指针
    void* any = NULL;
    
    // 这个指针可以指向int类型的变量
    any = &n;
    
    // 也可以指向double型
    any = &x;
    
    // 或者是一个对象
    any = &w;
    
    // 但是,如果想对该指针解引用,则必须用reinterpret_cast
    Widget* pw = reinterpret_cast<Widget>(any);
    
    // 然后就可以调用了,安全性需要程序员自己保证,如果类型不对,程序可能crash。
    pw->widgetMethod();
    

    所以,除非非常必要,不要使用任意指针。  

    指针是可以偏移解引用的,即使这个指针不是指向一个数组头部:p[i]等价于*(p+i)。这里的i不必是非负整数,还可以是负整数。比如p[-4]是合法的。

    相同类型的指针之差是合法的,比如

    int* begin = new int[100]; 
    int* end = begin+100; 
    int size = end - begin;     // 这是合法的,size = 100,表示begin和end之间的变量的个数
    

      

  • 相关阅读:
    数据库日志文件很大,如何变小!
    导出到CSV文件乱码的问题
    JQuery 常用方法一览
    马云在阿里巴巴十周年晚会上的激情演讲
    jqueryeasyui(替代 extjs) 介绍
    写一个ajax程序就是如此简单
    ASP.NET 3.5之屠龙刀
    因并发而生,因云计算而热(专家聊天实录)
    专家访谈:为什么我们需要Erlang
    《写给大家看的设计书》封面评选结果揭晓
  • 原文地址:https://www.cnblogs.com/bqzhao/p/3541924.html
Copyright © 2011-2022 走看看