pppploi8's Blog

欢迎来到pppploi8的个人博客!

C++ Primer学习笔记-指针

C++中指针有以下几种

int *pi;//普通的指针
int *const pi;//const指针,类型为int,指针不可修改,指向对象可以修改
const int *pi;//指向const对象的指针,类型为const int,指针可以修改,指向的对象不能修改
const int *const pi;//指向const对象的const指针,类型为const int,指针和指向的对象都无法修改
char **pc;//指向指针的指针,后面详细说明

指针的阅读顺序一般是从右往左阅读。如

const int *pi;//从右往左阅读,分别是*pi,一个指针,const int,代表一个指向const int类型的指针,指针可以修改但是指向对象不能修改
int *const pi;//从右往左阅读,*const pi,一个const指针,int,代表是一个指向int类型的const指针,指针无法修改但指向对象可以修改

另外,指向指针的指针大概最常见的例子就是main函数了

比如 int main(int argc,char **argv) 和 int main(int argc,char *argv[])是等价的

对argv第一次解引用,获得的是C风格字符串里char数组第一位的指针,第二次择循环解引用获取参数字符串

代码如下

#include <iostream>
#include <string>

using namespace std;

int main(int argc,char **argv){
    string s;
    for (int i=0;i!=argc;++i){
        char *pc=*(argv+i);//第一次解引用,遍历char *数组,取出每一个命令行参数的char *
        for (int j=0;*(pc+j)!=0;++j){
            s += *(pc+j);//第二次解引用,遍历char数组每一位组成string字符串
        }
        s += ' ';
    }
    cout << "您输入的命令行是:" << endl;
    cout << s << endl;
    return 0;
}

另外比较值得注意的是typedef

当使用typedef定义指针的时候,比如

typedef string *pstring;
const pstring cstr;

那么cstr是什么类型?const string *cstr?一个指向const string类型的指针?

然而并不是,typedef不同于define,它并非简单的文本替换,在const pstring cstr中,const修饰的是pstring类型,等价于

string * const cstr;

所以本质上它是一个指向string类型的const指针,指向的对象可以修改,而指针的值不可修改

另外还有一种特殊的指针,指向函数的指针,格式如下

void (*pf)(string s);

开头是返回值,中间是指针名变量名或者typedef定义的新类型名,后面是参数表,使用方法如下

//头文件省略
void print(const string &s){
    cout << s << endl;
}
typedef void (*pfunc) (const string &);//使用typedef定义指向函数的指针 
int main(){
    pfunc pf1 = print; 
    void (*pf2)(const string &) = print;//直接使用指向函数的指针 
    pf1("pf1:Hello World!");
    pf2("pf2:Hello World!"); 
    return 0;
}

值得注意的是中间一部分括号不能省略,如果省略,则变成了 void *pf (string s);这代表是一个void *指针,而不是指向函数的指针。

另外指向函数的指针也可以放在参数里,这时候中间部分则变成参数名或者新类型名,如下

//头文件依然省略
void print(const string &s){
    cout << s << endl;
}
typedef void (*pfunc) (const string &);//使用typedef定义指向函数的指针 
void call1(pfunc pf){
    pf("call1:Hello World!"); 
} 
void call2(void (*pf)(const string &)){//直接使用指向函数的指针 
    pf("call2:Hello World!"); 
} 
int main(){
    call1(print);
    call2(print); 
    return 0;
}

也可以当作返回值,中间值是函数定义或者成为新类型名,但是写法比较奇怪

//日常省略头文件
void print(const string &s){
    cout << s << endl;
}
typedef void (*pfunc) (const string &);//使用typedef定义指向函数的指针 
pfunc getProc1(){
    return print;
}
void (*getProc2())(const string &){//中间是函数格式,外面反而是指向函数指针的定义
    return print;
} 
int main(){
    getProc1()("GetProc1:Hello World!");
    getProc2()("GetProc2:Hello World!");
    return 0;
}

结论:typedef大法好←u←

暂时就这么多,等以后发现其他好玩的指针用法再补充