指针和引用html
区别数组
>引用在建立的时候须要初始化, 指向有效对象, 必须与合法的存储单元关联, 不能再改变为其余对象的引用;函数
>指针能够在定义之后任意时候再初始化, 指向的地址和地址内存放的数据均可以改变;spa
>引用不可为空, 指针能够为空 (0/NULL);翻译
>const指针能够是NULL, 也有多是野指针;
指针
>引用和指针的语义是类似的, 引用是不可改变的指针, 指针是能够改变的引用. 其实都是实现了引用语义. htm
常引用 对象
>利用引用提升效率 保护数据不被改变 const [type]& [name] = var; blog
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---