C++ Primer笔记(2.3.2)——指针
#include<iostream>
#include<cstdlib>
/*****************************************************************************/
/* 与引用类似,指针也是实现了对其他对象的间接访问。然而与引用不同的是: */
/* 1. 指针本身就是一个对象,允许对指针赋值和拷贝 */
/* 2. 指针无须在定义时赋初值,如果一个指针没有初始化,也拥有一个不确定的值 */
/*****************************************************************************/
int main()
{
/* ----- 例子 ----- */
//定义指针类型的方法是将声明符写成*d的形式,其中d是变量名。
int *ip1, *ip2; //ip1和ip2都是指向int型对象的指针
double dp, *dp2; //dp是double型对象,dp2是指向double型对象 的指针
/* ---------------- */
/* ----- 获取对象的地址 ----- */
//指针存放某个对象的地址,想要获取改地址,需要使用 取地址符&
int val = 42;
int *pv = &val; //p存放变量ival的地址,或者说p是指变量ival的指针
std::cout << "pv的值为:" << pv << "(即ival的地址)" << std::endl;
std::cout << std::endl;
//✳引用不是对象,没有实际的地址,所以不能定义指向引用的指针
//int& &v = ival; //错误
//指针的类型都要和它所指向的对象严格匹配
double dval;
double *pd = &dval;
double *pd2 = pd;
//int *pi = pd; //错误
//pi = &dval; //错误
/* -------------------------- */
/* ----- 指针值 ----- */
/********************************************/
/* 指针的值(即地址)应属下列4种状态之一: */
/* 1.指向一个对象 */
/* 2.指向紧邻对象所占空间的下一个位置 */
/* 3.空指针,意味着指针没有指向任何对象 */ /* 像&和*这样的符号,即能用作运算符,也能作为声明的一部分出现 */
/* 4.无效指针,也就是上述情况之外的其他值 */ /* 符号的上下文决定了符号的意义: */
/********************************************/ /* int i = 42; */
/* ------------------ */ /* int &r = i; //r是一个引用 */
/* int *p; //p是一个指针 */
/* p = &i; //&是一个取地址符 */
/* ----- 利用指针访问对象 ----- */ /* *p = i; //*是一个解引用符 */
//如果指针指向了一个对象,则允许使用解引用符(操作符*)来访问改对象。 /* int &r2 = *p //&是一个解引用符 */
int ival = 42;
int *p = &ival; //p存放着变量ival的地址,或者说p是指向变量ival的指针
std::cout << "p指向的值为:" << *p << std::endl;
*p = 0; //由符号*得到指针p所指的对象赋值
std::cout << "p指向的值为:" << *p << std::endl;
std::cout << std::endl;
/* ---------------------------- */
/* ----- 空指针 ----- */
//空指针不指向任何对象,在试图使用一个指针之前代码可以首先检查是否为空。
//三种生成空指针的方法:
int *p1 = nullptr;
int *p2 = 0;
//需要#include<cstdlib>
int *p3 = NULL;
//✳把int变量直接赋给指针是错误的操作,即使int变量恰好为0也不行
//int zero = 0;
//int *pi;
//pi = zero; //错误
/* ------------------ */
/* ----- 赋值和指针 ----- */
/**************************************************************/
/* 指针和引用都能提供对其他对象的间接访问,然而两者有很大不同 */
/* 其中引用本身并非一个对象,一旦定义了引用,就无法令其再绑定 */
/* 到另外的对象,之后每次使用这个引用都是访问它最初绑定的对象 */
/* */
/* 而指针没有这种限制,指针和其他变量一样,给指针赋值就是令它 */
/* 存放一个新的地址,从而指向一个新的对象。 */
/**************************************************************/
int i = 42;
int *pi = 0; //pi空指针,没有指向任何对象
int *pi2 = &i; //pi2存有i的地址
int *pi3; //没有对pi3初始化,如果pi3定义于块内,则pi3的值是无法确定的
std::cout << "pi 的值为:" << pi << std::endl;
std::cout << "pi2的值为:" << pi2 << " " << "pi2指向的值为:" << *pi2 << std::endl;
//std::cout << "pi3的值为:" << pi3 << std::endl; //错误,因为值无法确定,无法打印
std::cout << std::endl;
pi3 = pi2; //pi3和pi2指向同一个对象i
pi2 = 0; //现在pi2不指向任何对象了,空指针
std::cout << "pi2的值为:" << pi2 << std::endl;
std::cout << "pi3的值为:" << pi3 << " " << "pi3指向的值为:" << *pi3 << std::endl;
std::cout << std::endl;
//有时候要想搞清楚一条赋值语句到底是改变了指针的值还是改变了指针所指对象的值是不太容易的。
//最好的办法是记住赋值永远改变的是等号左侧的对象。
ival = 42;
pi = &ival; //pi的值改变,现在指向ival
std::cout << "pi的值为:" << pi << " " << "pi指向的值为:" << *pi << std::endl;
*pi = 0; //ival的值被改变,指针pi并没有变化
std::cout << "ival的值为:" << ival << std::endl;
std::cout << "pi的值为:" << pi << " " << "pi指向的值为:" << *pi << std::endl;
/* ---------------------- */
return 0;
}
``