【C++】《C++ Primer Plus》笔记(2)——指针

指针与C++基本原理
指针的声明和初始化
指针和数字
指针与内存分配


指针与C++基本原理

面向对象的编程和传统的过程性编程的区别在于, OOP强调在运行阶段(而不是编译阶段)进行决策
运行阶段指的是,程序正在运行时,编译阶段指的是编译器将程序组合起来时。
运行阶段进行决策提供了灵活性,可以根据当时的情况进行调整。
例如,为数组分配内存的情况,传统的情况是声明一个数组,而在C++中声明数组,必须提前指定数组的长度,因此,数组的长度在编译时就已经确定好了,这就是编译阶段的决策.为了安全起见,通常数组开得都比较大,但程序在大多数情况下都是浪费了内存的
OOP将这样的决策推迟到运行阶段,来动态地确定数组的长度。C++采取的方法是,使用关键字new来请求正确数量的内存以及使用指针来跟踪新分配的内存的位置。
OOP并非C++独有,但是C++这一特性,使得代码比C语言简单。


指针的声明和初始化

指针名表示的是地址。*运算符,称为间接值(indirect value)0 )或者解除引用(dereferencing)运算符,将其应用于指针,可以得到该地址处所储存的值(C++是根据上下文来确定所指的值是乘法还是解除引用)。例如p是一个指针,则p表示的是一个地址,*p表示存储在该处的值



/**@brief 演示指针的用法
*
* lq_pointer_demo(),通过简单的示例演示了指针的用法
*/

void lq_pointer_demo()
{
                 using namespace std;
                 int target = 1;
                 int *pointer;
                pointer = ⌖

                cout << "target=" << target << endl;
                cout << "*pointer=" << *pointer << endl;

                cout << "Address:&target=" << &target ;
                cout << ",pointer=" << pointer << endl;

                cout << "Now, use pointer to change the value..." << endl;
                *pointer = *pointer + 200;
                cout << "Now target=" << target << endl;
                cout << "*pointer=" << *pointer << endl;

                cout << "Address:&target=" << &target ;
                cout << ",pointer=" << pointer << endl;

}


Tip:*两边的空格是可选的,通常,C程序员使用这种格式:
int *ptr;
来强调*ptr是一个int类型的值.

而C++程序员很多采用这种格式:

int* ptr;
来强调int* 是一种类型——指向int类型的指针。
这两种格式对于机器来说没有区别,甚至不加空格,或者*两边都有空格也没有关系。

和数组一样,指针都是基于其他类型的,但指向不同类型的指针,它们本身的长度通常是相同的。地址的长度,既不能指示关于变量的长度或类型的任何信息,也不能指示该地址上有什么值。
一般来说,地址需要2或者4个字节,这取决于计算机系统(有些系统可能需要更大的地址,系统可以针对不同的类型使用不同长度的地址)。


!!!指针的危险

一定要在对指针使用*(解除引用运算符)之前,将指针初始化为一个确定的、适当的地址!!!

例子:
long *ptr;
*ptr=250;
ptr没有初始化,所以其可能是任何值。而按照程序,不管其是任何值,其都会被解释为存储250的地址。ptr指向的地方,可能并非是要存储250的地方,因此可能导致最隐秘、最难跟踪的bug.



指针和数字


指针和整型式截然不同的类型,不能简单地将整数赋值给指针;
例如:
int *ptr;
ptr=0x001AFD28;//违法,左侧为指向int型的指针,右侧为整型

可以通过强制类型转换,将数字转换为合适的地址
int *pt;
ptr=(int* )0x001AFD28;//类型匹配

但是,pt是int型的地址,但不表示pt本身就是int型。有些平台中,int 类型是2个字节,而地址则是4个字节。



指针与内存分配

指针真正的用武之地在于——在运行阶段分配未明名的内存来存储值,这种情况下,只能通过指针来访问内存。
在C中,可以使用库函数malloc( )来分配内存;C++除此之外,还有更好的方法,就是new运算符!

new运算符的作用就是为一个数据对象(可以是结构,也可以是基本数据类型)找到一个长度正确的内存快,并返回该内存块的地址。
通用使用格式格式如下:

typeName * pointer_name = new typeName;

和传统的指针初始化方法:

typeName   target;
typeName*  pointer_name=&target;

两者相比 ,使用new建立的指针指向的内存没有名称,它使得程序在管理内存方面有更大的控制权。



/**@brief 用来演示new动态分配内存的过程
* @param 无
* void lq_use_new_demo()
*/

void lq_use_new_demo()
{
                 using namespace std;
                 int * p1 = new int ;
                *p1 = 1001;

                 double * p2 = new double ;
                *p2 = 1001.0;

                cout << "int value=" << *p1 << ", location=" << p1 << endl;
                cout << "double value=" << *p2 << ", location=" << p2 << endl;

                cout << "size of p1=" << sizeof (p1) << ", size of *p1=" << sizeof (*p1) << endl;
                cout << "size of p2=" << sizeof (p2) << ", size of *p1=" << sizeof (*p2) << endl;
}

例子中int 指针和double指针的长度相同,都是地址,但是由于声明了指针的类型,所以显示出(*p1)是4字节的int型,(*p2)是8字节的double型。


对于指针,new分配的内存块通常和常规变量声明分配的内存块不同,变量的值都存储在称为栈(stack)的内存区域中,而new从被称为堆(heap)或者自由存储区(free store)的内存区域分配内存。

对于内存耗尽以及分配失败的情况,C++提供了相应的处理机制和工具。


new 一定要和 delete 配对使用!!!
也就是,只能用delete来释放使用new分配的内存,但是对于空指针使用delete是安全的。

否则可能发生内存泄漏(memory leak)的情况,被分配的内存再也无法使用。如果内存发生严重泄漏,则程序将会由于不断寻找更多内存而终止。
int *ptr = new int;
...
delete ptr;
这样将会释放ptr指向的内存,但是不会删除ptr本身。需要时,还可以将ptr重新指向一个新分配的内存块。


另外:不要释放已经释放的内存块(这样做,结果将是不确定的);
不能使用delete来释放声明变量所获得的内存


























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值