查看: 156|回复: 1

C++基础:指针与引用

[复制链接]

3

主题

6

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2023-2-14 18:44:21 | 显示全部楼层 |阅读模式
作为一个转码人员,我自己是最早学了python,后来开始写Java,最后开始写C++的,个人认为,对于C++入门来说,最重要的知识,就是对于指针与引用的理解和使用,对于指针和引用的理解不到位,是最容易引发crash且感到怀疑人生的,此篇博文将会尝试介绍C++中的指针及引用的概念,下面引用了《C++ Primer 5th》中的部分例子
引用与指针

谈论到指针和引用,不得不说到 & 和 * 这两个符号,正是因为这两个符号拥有多重含义,才会照成新手的迷惑。
引用
引用即变量的另一个名字,引用符长 & 这样,至于对象左侧 ,即 &x
int i = 1024;
int & ref_i = i;
在这里,ref_i就相当于i,i如果变了,ref_i的值也会变, 同样,如果我们改了ref_i的值,i的值也会变
int i = 0;
int & ref_i = i;
std::cout << ref_i << std::endl; //输出0
i = 1;
std::cout << ref_i << std::endl; //输出1
ref_i = 2;
std::cout << i << std::endl; //输出2
指针

指针是指向另一种类型的对象,定义指针时,需要写成*x的形式。指针存放的是对象的地址,因此,我们在对指针赋值时,需要使用取地址符。不幸的是,取地址符长这样:&
int ival = 42;
int *p = &ival;
注意,指针和引用的类型都必须和指向对象一致。
现在我们拥有了一个指针,那么应该怎样使用指针呢。我们需要对指针进行解引用,通过该操作可以从指针访问指向对象,不幸的是,解引用符长这样:*
cout << *p; //输出42
*和&的多重含义

实际上,正是C++中符号的多重含义令初学者费解。我们再看看上面出现的几次符号:
int i = 42;
int &r = i //&随类型名int出现,作为声明的一部分,组成复合类型int &
int *p = &i; //*紧随类型名int出现,是声明的一部分,组成符合类型int *,&出现在表达式中,是一个取地址符
cout << *p; //*出现在表达式中,是一个解引用符
int &r2 = *p; //int &是复合类型,表示int型的引用,*是一个接引用符,*p是一个int型
*和&中的空格

int &ref_i, int& ref_i, int &ref_i 这么写都是一样的,空格没有影响,ref_i的变量类型就是int &,即,指针型的引用,但是,为了防止产生误导,我们推荐用int &ref_i这样的写法,将引用符和变量名写到一起,指针也是如此,我们推荐写成int *p
如何阅读复杂类型的声明

学完了基础知识,我们现在来看点复杂的但也经常出现的内容:
指向指针的指针
在实际工作中有时会遇到二级指针,即指向指针的指针,只需增加*的个数即可,而解引用也需要两次
int i = 1024;
int *pi = &i;
int **ppi = π
std::cout << **ppi; //输出1024,实际上等于*(*p)
指向指针的引用
让我们看看下面这段代码中的r,那么它的类型 int *&是指什么呢?
int i = 42;
int *p = &i;
int *&r = p;
实际上,对于声明,我们是从右到左阅读的。离变量名最近的符号对变量的影响是最大的。因此,r是一个引用。那么,这个引用的类型是什么呢?离r最近的符号是*,说明r引用的是一个指针,也就是说,r是一个引用了 int型指针 的对象。那么,如果我们想使用r指向对象的值,要怎么做呢?记住,r本身是指针的引用,我们直接打印r,相当于打印指针地址,如果我们需要使用指针指向的值,只需要解引用r即可。
std::cout << p << std::endl; //打印的是0x7ffeee86030c,表示i的地址
std::cout << r << std::endl; //打印的是0x7ffeee86030c,同p一样
std::cout <<*r;函数参数中的& //输出42,相当于*p
函数参数中的&: 引用类型的形参

在C++中,我们知道,函数的形参会对实参进行拷贝(除了引用类型,下面会介绍),如:
void hello(string s1)
{
  s1 = s1 + "a"; //此处不会修改main函数中s1的值
  cout << s1 << endl;
}

int main()
{
    string s1 = "hello";
    hello(s1); //打印hello
    cout << s1; //打印helloa
}
而我们在代码中有一种经常见到的写法,这里解释一下含义
void hello1(string &s1)
{
  std::cout << s1;  s1 = s1 + "a";
  cout << s1 << endl;
}
我们看到上面的函数中,s1 前面跟了一个&,这是什么意思呢?在C++中,若函数的形参加了一个&符,那么,这个形参不会拷贝实参的值,而是传递给函数一个引用对象,此时,在函数内的修改会影响到函数外的传参。这是我们再打印:
int main()
{
    string s = "hello";
    hello1(s); //打印helloa
    cout << s; //打印helloa,值被函数改变了
}
在需要拷贝大的对象或者使用某些不支持拷贝操作的对象时,使用引用类型的形参不可避免。
回复

使用道具 举报

3

主题

13

帖子

23

积分

新手上路

Rank: 1

积分
23
发表于 2025-2-23 09:39:02 | 显示全部楼层
我只是路过,不发表意见
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表