指针和引用(整理)

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

指针和引用

区别

>引用在创建的时候需要初始化, 指向有效对象, 必须与合法的存储单元关联, 不能再改变为其他对象的引用;

>指针可以在定义以后任意时候再初始化, 指向的地址和地址内存放的数据都可以改变;

>引用不可为空, 指针可以为空 (0/NULL);

>const指针可以是NULL, 也有可能是野指针;

>引用和指针的语义是相似的, 引用是不可改变的指针, 指针是可以改变的引用. 其实都是实现了引用语义.

常引用

>利用引用提高效率 保护数据不被改变 const [type]& [name] = var;

Note 用基类指针操作派生类的数组, p++不是指向下一个元素, 而是指向了一个不合适的内存地址(类型不同); void* p; 不能++;

---End---


函数传参

传值

>函数内会为形参开辟一个新的内存空间存放实参的值, 是实参的副本;

>指针是个存放地址的变量,传递指针参数本质上是值传递, 传递的是内存地址, 固定大小(一个pointer, 一般为4);

>如果函数的形参为字符串指针, 那传递的是地址值, 在函数内部修改形参的值并不能真正的改变传入实参的值;

void GetMemory( char* p )
{
    //改变了作为形参的指针的地址变量, 不会对实参有影响;
    p = (char*) malloc( 100 );
}

>p[]数组为函数内的局部自动变量, 栈内存在函数返回后内存已经被释放;

char* GetMemory( void)
{
    char p[] = "hello world";
    return p;
}

传指针

>如果是修改指针指向的地址存放的值, 这样可以改变实参的值;

void GetN(int* n)
{
    *n = 3;
}

>要改变指针指向的地址, 使用指针的指针, 或者指针的引用;

void GetMemory( char** p, int num )
{
    //这里需要判断是否申请成功 if(*p == NULL), 需要释放free;
    *p = (char*) malloc( num );
}

传引用

>引用是内存别名, 定义需要初始化, 存在依附性, 地址不可改变;

void GetMemory( char* &p, int num )
{
    p = (char*) malloc( num );
}

>引用传递中, 函数的形参虽然也作为局部变量在栈中开辟了内存空间, 但是存放的是函数传递进来的实参的地址; 对形参的操作会被处理成间接寻址(通过栈中存放的地址访问实参的数据变量).

>引用不产生对象副本(不会调用构造), 参数传递时不需要复制对象, 提高效率;

>如果函数返回了引用, 那么函数的调用也可以被赋值;

double &max(double &d1,double &d2)
{
    return d1>d2?d1:d2;
}
//---
max(x,y)+=1.0;

<refer to> http://xinklabi.iteye.com/blog/653643

---End---


指针数组和数组指针

指针数组-存储指针的数组; int* p[n]: 声明了一个数组, 数组的元素是n个int型的指针;
[]的优先级比*高, p和[]先结合成为数组;  p是指向数组首地址的指针; [原文说p是个不可知的表示]
[原文说:执行p+1是错误的, 但(p+1)就是指向p[1]的指针, 就是指向数组元素(int指针)的指针)]

>指针数组是多个指针变量, 以数组的形式存放在内存中, 占有n个指针的存储空间;

>二维数组赋给指针数组:

int *p[3];//数组存放了3个指针变量 p[0]~p[2]
int a[3][4];
for(i=0;i<3;i++){
    p[i]=a[i];
}

表示数组中i行j列的元素的方式: *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

数组指针-指向数组的指针; int (*p)[n]: 声明了一个指针, 指向一个拥有n个int元素的数组;
()的优先级高, p和*结合成为指针; 这个一维数组的指针也称为行指针, p+1时, p会跨过n整个整型数据的长度(步长), 也就是跨过数组;

>数组指针是一个指针变量, C语言中用来指向二维数组, 内存中只占一个指针的存储空间;

Class **Menu = new Menu*[NUM]; //指针指向数组, 数组的内容是指针, 即: 指针数组的数组指针...

>二维数组赋给数组指针:

int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

<refer to> http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html


指针和数组

char str[] = "world"; cout <<str<<" "<< sizeof(str) << ": ";
char* p    = str;     cout <<p<<" "<<sizeof(p) << ": ";

>str是数组名, 编译器通过数组名查到数组大小, str是C风格的字符串, 长度需要加上一个\0;

>p是指针, 长度为一个地址, 大小不变, 一般情况下, 32位是4, 64位是8;

>不变的还有char, 占一个机器字节;

---End---


常量指针和指针常量

>常量指针- 指向常量的指针; 指针指向的内容不可修改, 指针自身的地址值可变;

const在*左边: const char* ptr; 或 char const* ptr; 读作: pointer to const char: 指向const char的指针; (内容不变)

>指针常量- 指针是一个常量; 指针内存储的地址值不可变, 指向的数据内容可修改;

const在*右边: char* const ptr; 读作: const pointer to char: const指针, 指向char; (地址不变)

[中文翻译坑爹, 用英文理解就很清晰, 中文应该记成: 常量的指针, 指针是常量]

int a = 1;
int b = 2;
int* pa = &a;
int* const* pointerToConstPointer = &pa;
int* pb = &b;
pointerToConstPointer = &pb;
*pointerToConstPointer = pb; //error
**pointerToConstPointer = 10;

>对于模板形式有点不同:

//1
std::vector<int>::const_iterator Iter = vec.begin(); //内容是const的
*Iter = 10;//错误,Iter是常量指针
Iter++;//正确,Iter本身可变
//2
const std::vector<int>::iterator Iter = vec.begin(); //地址是const的
*Iter = 10; //正确,指针常量
Iter++;     //错误,指针本身不可变

<refer to> http://www.cnblogs.com/xfxsworld/archive/2008/01/30/1059303.html & http://www.gocalf.com/blog/cpp-const-and-pointer.html

---End---


OTHER

重载运算符不能对指针单独操作

>因为系统已经定义了两个指针的运算, 你不能改变它; e.g. 两个同类型的指针相加, 就是地址相加, 如果编译器未定义就是无意义的;

Note 指针之间可以相减, 但不可以相加: 两个同一类型的指针变量是可以相减的, 他们的意义表示两个指针指向的内存位置之间相隔多少个元素(注意是元素, 并不是字节数) 例如对于int类型的指针p和p1. p1-p的意义表示他们之间相隔多少个int类型的元素. 同样对于其他类型的指针变量之间相减的意义也是一样.

>运算符重载参数必须至少有一个类类型的形参;

friend Test operator * (const Test &src1, const Test *src2) //ok
friend Test operator * (const Test *src1, const Test *src2)//error

---End---

引用,其实不可以改变指向 今天跟几位同学讨论了一点小问题,最后谈到指针引用的区别……最后,谈到引用永远指向初始化它的对象。。。问题就从这里提出。按我的理解,引用是可以改变指向的(说明:这是错误的思维)。 #include using namespace std;   int main(int argc, char *argv[]) { int a = 10, b = 20 阅读详情

相关推荐

指针引用

指针保存一个对象的地址,通过该地址访问对象;引用是对象的别名。二者在概念及使用上需要分清楚。        引用不可以为空,指针可以为空。定义一个引用的时候,必须初始化;声明指针是可以不指向任何对象,即空指针。因此如果一个变量是用于指向另一个对象,它可能为空,这时你应该使用指针;如果变量总是指向一个对象,且不允许变量为空,这时你应该使用引用。由于指针可能为空,使用指针之前必须做判空操作,而引用

爱很遥远 499

C++引用不可改变指向的理解

首先引用的本质是一个指针常量,即int &p=a 等价于 int * const p=&a。指针常量的意思是指针变量中保存的地址不能修改,也就是说不能改变指针指向,既然引用的本质是一个指针常量,当然也不能改变引用指向了。 下面代码11行进行c=b操作后,c的值变成了4,乍一看还以为是c改变指向,从指向a变成了指向b,其实仔细想想,这其实只是赋值操作罢了。 复制代码 1 #include 2 #include 3 using namespace std; 4 5 int main()

luronggui的博客 2108

指针引用

引用就像是一个人的小名一样,它可以有多个但终究代表的是一个人。在C++中,变量的引用就是变量的别名。 一.在使用引用的过程中,我们需要注意以下几点: 1.在声明引用时必须立即对它进行初始化;   int i=10;   int &j;   j=i;                 //错误,不能声明完成后再赋值 2.变量类型要相同;   double a;   int &b=a; 

qq_29503203的博客 579

引用指针有什么区别

本质:引用是别名,指针地址,具体的: ①从现象上看,指针在运行时可改变其所指向的值,而引用一旦某个对象绑定后就不在改变。这句话可以这样理解:指针可以被重新赋值以指向另一个不同的对象。但是引用指向在初始化时被指定的对象,以后不能改变,但是指定的对象内容可以改变。 ②从内存上分配看,程序为指针变量分配内存区域,而不用为引用分配内存区域,引用声明时必须初始化,从而指向一个已经存在的对象,引用不...

望那伊人的博客 1万+

C++ 指针引用 吐血整理 Pointer&Reference

说道C++的指针,很多人都很头疼,也很confuse。经常把它变量名,引用(reference)等混淆,其实这最主要的原因是很多程序员对于基本知识的掌握有问题,从而导致的很多基本概念的混淆。本文就是从最基本的概念讲起,着重分析比较指针引用。主要从以下几个方面着重的讲解: 1. 变量(variable)的表现形式; 2. 指针的结构原理; 3. 引用的结构原理; 4. 指...

Abcs12345789的博客 625

c/c++易错知识点整理3(引用指针)(一)

1.一般变量引用 #include #include using namespace std; int main() { int a=10; int b=20; int &rn=a; int equal; rn=b; rn=100 equal=(&a==&rn)?1:0; } a=10;b=20;

JeremyZJM的博客 498

C++指针传递引用传递的区别 (转载整理

区别1:指针传递引用传递是以不同的方式实现相同的效果,但是指针传递的本质还是值传递,只是传递的值是地址。 就拿 交换两个数的函数来举例: // 指针传递 void swap(int * val1, int * val2) { int temp; temp = *val1; *val1 = *val2; *val2 = temp; }...

aiqianqi1796的博客 5005

c/c++整理--引用指针(4)

一、指针数组数组指针的区别 解析:   指针数组指用于存放指针的数组,存放同一类型的指针,例: int *a[10];数组a中存放了10个int*型变量,在栈区分配了10个int*的空间,数组存放10个int型数据的地址。   数组指针指向一个数组的指针,例: int *b = new int[10];指针b指向在堆中分配的10个int型数据大小的内存区,注意,这个时候释放空间一定要

hjf161105的博客 275

c/c++整理--引用指针(2)

一、参数引用的常见错误 找错 #include <iostream> using namespace std; class Test { public: void f(const int& arg); private: int value; };...

chengni9565的博客 110

c/c++整理--引用指针(1)

一、一般变量引用 看代码写输出 #include <iostream> using namespace std; int main() { int a = 10; int b = 20; int &rn = a; int equal; rn = b...

chengni9565的博客 134

习题整理《C++17从入门到精通》第五章-复合类型:数组、指针引用

虽然 &i 是一个有效的地址,但是将 &i 赋给 long* 类型的指针 lp 是非法的。p2 是一个指向常量整数的指针,可以通过改变指向的对象来修改 ci 的值,而 p3 也是一个指向常量整数的指针,因此可以将 p3 的值赋给 p2。//ip是指向int型变量的指针,&r=ip 表示r是一个引用指向ip所指向的整型数据。r的类型为int,其值为ip所指向地址。p2 是一个指向常量整数的指针指向 ci,p2 可以通过改变指向的对象来修改 ci 的值,但是 p2 本身是一个常量指针,不能被修改。

Kethy__的博客 2251

c/c++整理--引用指针(3)

一、找错——内存访问违规 #include using namespace std; int main() { char a; char *str1 = &a; char *str2 = "AAA"; strcpy(str1, "hello"); cout<<str1<<endl; str2[0] = 'B'; cout<<str2<<endl; return 0;

hjf161105的博客 494

c/c++整理--引用指针(5)

一、什么是“野指针”   “野指针”不是NULL指针,而是指向“垃圾”内存的指针,其成因主要为:指针变量没有被初始化,或指针p被free或者delete之后,没有置为NULL。 二、“野指针”的危害 下面程序有什么重大的bug? sho...

chengni9565的博客 117
上一篇: 位, 字节和字 bit, byte and word
下一篇: Templat 模板(整理)
罗伊yc
博客等级 码龄22年 23粉丝 113原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值