c++指针

已经从事编程(C++ Qt)工作半年了,突然有了想写博客的想法,那么就先从指针说起吧,希望能帮助到像我刚接触c++时的一些小白们,如果真正理解了指针,那么就离入门c++不远了,因为c++真的是无时无刻不与指针打交道,这里就先不说指针的一些最基本的操作了,只是说一下操作指针时容易犯错的地方或者难理解的地方。
**一:指针和const:**注意,const比*会更早地与int结合。
1.常量指针变量:仅指向唯一内存地址的指针常量 <指针类型 *> const <变量名>
int aa=1; int * const a=&aa; //声明必须紧接着初始化,因为此时指针a是指针常量,不允许修改。
2.常量指针:指向某个指针变量的值。 const <指针类型 *> <变量名>
int aa=1; const int a=&a;; // a一旦初始化后,不能通过a来改变aa的值(*a是const int)。
3.指针常量:满足常量指针变量和常量指针的要求的指针。
const <指针类型 *> const <变量名>

一个量是变量还是常量,要看是不是const直接修饰的它,const int * a; const修饰的是int,因此(*a)就是常量,a不是常量。
字节序:描述数据存储在内存中的排序。
大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。
小端字节序:低位字节在前,高位字节在后,这是计算机内部采用的,即低位存放在地址小的地址,高位存放在地址大的地址。

二:为什么有小端字节序:
计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。但是,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。(网络编程时,需要网络字节序和主机字节序之间的转换)
转换:

两个相同类型指针变量不能相加,但是可以想减:
int a[] = { 1,2,3,4,5 };
int *b = a;
int *c = a + 4;
cout <

**三:void ***
如果声明一个指针的时候不明确它指向的类型,应该用void *。
任何类型的指针都能指向void *,但是不能将void 指针赋给其它指针,除非进行显式转换。
注意:void
指针尽量别进行++等操作,因为有不同的标准。

四:指针数组和数组指针:
指针数组:元素为指针的数组。 int* a[5];
数组指针:指向数组的指针。 int (* a)[5]; //多用于多维数组

多维数组:
二维数组:在c++中 数组可被看做是一种类型,但是不存在“二维数组”的类型,其可被看做是一位数组。
int a[2][3]; 可被看做一个元素个数为2,元素类型为int a[3]的一维数组。

普通声明: int a[2][3]; 这种方法声明的内存是连续的,a是指向int[3]的指针,*a是指向int的指针,**a才是int类型。
动态声明: 1. 使用数组指针: int (*a)[3]=new int [2][3]; delete []a;
2. 使用指针间接引用(可以不用对齐):
int *a=new int[height];
for(int i=0;i 缺点:行与行之间内存不连续。
释放内存时: for(int i=i;i delete [] a; //回收高级的
3.利用vector
vector a(height,vector(width));
缺点:行与行之间内存也不是连续的。
三维数组:二维数组是在一位数组每个元素上产生分支,那么三维数组就是在二维数组的每个元素上再产生分支。

五:内存对齐:
typedef struct { typedef struct{
int a; int a;
double b; short b;
short c; double c;
}A; }B;
Sizeof(A)=24; sizeof(B)=16;

对其规则:
1.对于结构(类)的各个成员,第一个成员位于偏移为0的位置,以后的每个数据成员的偏移量必须是 min(#pragma pack())指定的数,这个数据成员的自身长度)的倍数 对于A:4(sizeof(int))+4+8(sizeof(double))+2(sizeof(short))+6
2.在所有的数据成员完成各自对齐之后,结构或联合体本身也要进行对齐,对齐将按照 #pragram pack 指定的数值和结构或者联合体最大数据成员长度中比较小的那个 也就是 min(#pragram pack() , 长度最长的数据成员);
设置对齐参数:#pramgma pack(n); n为2的整数倍
使用默认对齐参数:#pramgma pack(); 对齐参数64位是8;
为什么进行内存对齐:
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
解释:CPU把内存当成是一块一块的,块的大小可以是2、4、8、16字节等大小(即对齐参数)。CPU在读取内存的时候是一块一块读取的。块大小即memory access granularity:内存读取粒度。
若未内存对齐:int分布在6,7,8,9 则读取两块内存,然后删了0,1,2,3,4,5,10,11,12,13,14,15这些多余的,再把6,7,8,9拼在一起。然而内存对齐后只需读取一块内存。

六:智能指针:
头文件
智能指针都是指向堆内存,用于动态内存分配。

重载运算符-> 会返回智能指针内部所维护的指针,因此智能指针对象p,p->show(),表示的是调用智能指针内部维护的指针的方法。

1.shared_ptr:
采用引用计数,只要有shared_ptr指针指向该内存,引用计数就递增,指向该内存的shared_ptr指针过期或者指向别处,引用计数递减,当引用计数等于0时,内存销毁。

2.unique_ptr:
某一时刻,只能有一个unique_ptr指向一个对象,因此不支持普通的复制和赋值操作。但可以通过成员函数release()和reset()改变指针的所有权。unique_ptr对象销毁,其所指向的对象也销毁。
若一个右值赋给unique_ptr对象,程序不会报错,因为右值即将销毁,不会访问数据。

3.weak_ptr:
用shared_ptr构造,但不会对shared_ptr的引用计数造成任何变化。
使用时可以用成员函数lock(),若指向的对象的引用计数为0,则返回一个空的shared_ptr;否则,返回shared_ptr。

你可能感兴趣的:(c++,c++)