【C++注意事项】4 指针 Pointers

和上一节的引用类似,指针(pointer)是“指向(point to)”另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然后指针和引用相比有许多不同。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。其二,指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

因为引用不是对象,没有实际地址,所以不能定义指向引用的指针。

指针的值(即地址)应属下列4种状态之一:

1)指向一个对象

2)指向紧邻对象所占空间的下一个位置

3)空指针,意味着指针没有指定任何对象

4)无效指针,也就是上述情况之外的其他值

试图拷贝或以其他方式访问无效指针的值都将引发错误。编译器并不负责检查此类错误,这一点和试图使用未经初始化的变量是一样的。访问无效指针的后果无法预计,因此程序员必须清楚任意给定的指针是否有效。因此解引用符也只适用于那些确实指向了某个对象的有效指针。

所谓的解引用符就是使用操作符*来访问指针指向的对象。

int ival= 42;
int *p= &ival;  // p存放着变量ival的地址,或者说p是指向变量ival的指针
cout<<*p;  // 由符号*得到指针p所指的对象,输出42
*p= 0;  // 由符号*得到指针p所指的对象,即可经由p为变量ival赋值
cout<<*p;  // 输出0

取地址符(&)和解引用符(*)的多重含义:

int i= 42;
int &r= i;  // &紧随类型名出现,因此是声明的一部分,r是一个引用
int *p;  // *紧随类型名出现,因此是声明的一部分,p是一个指针
p= &i;  // &出现在表达式中,是一个取地址符
*p= i;  // *出现在表达式中,是一个解引用符
int &r2= *p;  // &是声明的一部分,*是一个解引用符

空指针(null pointer)不指向任何对象,在试图使用一个指针之前代码可以检查它是否为空。下面有3种生成空指针的方式:

// 需要首先#include cstdlib
inht *p1=NULL;

过去的程序会用到一个名为NULL的预处理变量(preprocessor variable)来给指针赋值,这个变量在头文件cstdlib中定义,它的值就是0。

int *p2= 0;

直接将p2初始化为字面常量0

int *p3= nullptr;

这是C++11新标准所引入的一种方法。

需要注意的是不能将int变量直接赋值给指针,即便int变量的值恰好等于0也不行。

void*是一种特殊的指针类型,可用于存放任意对象的地址。

但是不能直接操作void*指针,因为我们并不知道这个对象到底是什么类型,也就无法确定能在这个对象上做哪些操作。



English…



With two exceptions, which we will see at later, the types of the pointer and the object to which it points must match:

double dval;
double *pd= &dval;  // ok: initializer is the address of a double
double *pd2= pd;  // ok: initializer is a pointer to double
int *pi= pd;  // error: types of pi and pd differ
pi= &dval;  // error: assigning the address of a double to a pointer to int

The types must match because the type of the pointer is used to infer the type of the object to which the pointer points. If a pointer addressed an object of another type, operations performed on the underlying object would fail.

As with reference, we can define pointers that point to either const or not const types. Like a reference to const, a pointer to const may not be used to change the object to which the pointer points. We may store the address of a const object only in a pointer to const:

const double pi= 3.14;  // pi is const; its value may not be changed
double *ptr= &pi;  // error: ptr is a plain pointer
const double *cptr=&pi;  // ok: cptr may point to a double that is const
*cptr= 42;  // error: cannot assign to *cptr

The first exception is that we can use a pointer to const to point to a nonconst object:

double dval= 3.14;  // dval is a double; its value can be changed
cptr= &dval;  // ok: but can't change dval through cptr

Defining a pointer as a pointer to const affects only what we can do with the pointer. It is important to remenber that there is no guarantee that an object pointed to by a pointer to const won’t change.

It may be helpful to think of pointers and reference to const as pointers or references “that think they point to refer to const.”

const pointers

Unlike references, pointers are objects. Hence, as with any other object type, we can have a pointer that is itself const. Like any other const object, a const pointer must be initialized, and once initialized, its value(i.e., the address that it holds) may not be changed. We indicate that the pointer is const by putting the const after the *. This placement indicates that it is the pointer, not the pointed-to type, that is const:

int errNumb= 0;
int *const curErr= &errNumb;  // curErr will always point to errNumb
const double pi= 3.14159;
const double *const pip= &pi;  // pip is a const pointer to a cosnt object

The symbol closest to curErr is const, which means that curErr itself will be a const object. The type of that object is formed from the rest of the declarator. the next symbol in the declarator is *, which means that curErr is a const pointer. Finally, the base type of the declaration completes type of curErr, which is a const pointer to an object of type int. Similarly, pip is a const pointer to an object of type const double.

The fact that a pointer is itself const says nothing about whether we can use the pointer to change the underlying object. Whether we can change that object depends entirely on the type to which the pointer points. For example, pip is a const pointer to const. Neither the value of the object addressed by pip nor the address stored in pip can be changed. On the other hand, curErr addresses a plain, nonconst int. We can use curErr to change the value of errNumb:

*pip= 2.72;  // error: pip is a pointers to const
// if the object to which curErr points(i.e., errNumb) is nonzero
if(*curErr)
{
    errorHandler();
    *curErr= 0;  // ok: reset the value of the object to which curErr is bound
}


Note: “C++ Notes” series of blog mainly reference books of C++ Prime is the fifth edition of the Chinese version and English version. My English is very poor, and I don’t want there are some syntax error in blog. So the blogs have lots of words and sentences from the book. I wrote this series in order to consolidate the knowledge of C++, but also in order to improve my poor English. I also hope to help readers. Thank you.、




感谢您的访问,希望对您有所帮助。 欢迎大家关注、收藏以及评论。

我的更多博客文章:NoMasp博客导读



为使本文得到斧正和提问,转载请注明出处:
http://blog.csdn.net/nomasp


时间: 2024-10-21 22:42:52

【C++注意事项】4 指针 Pointers的相关文章

基于指针pointers和引用references的区别分析_java

指针用"*"和"->"操作符,引用用"."操作符,当然这是表面的区别.     1.引用必须代表一个对象,没有所谓的空引用.指针可以为NULL.即引用必须有初值,指针不然.所以在使用pointers之前,必须测试它是否为null.references不需要测试.     2.pointers可以被重新赋值,指向另一个对象,reference总是指向(代表)它最初获得的那个对象: 复制代码 代码如下: string s1("Nanc

C++中Reference与指针(Pointer)的使用对比

了解引用reference与指针pointer到底有什么不同可以帮助你决定什么时候该用reference,什么时候该用pointer. 在C++ 中,reference在很多方面与指针(pointer)具有同样的能力.虽然多数C++程序员对于何时使用reference何时使用pointer 都会有一些直觉,但总还是会有些时候搞不清楚.如果你想要建立一个关于使用reference使用的清晰有理的概念, 又有必要了解到底reference和pointer有什么不同. 深层含义 与pointer 类似

C语言中的指针和内存泄漏

引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具. 本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密.本文内容包括: 导致内存破坏的指针操作类型 在使用动态内存分配时必须考虑的检查点 导致内存泄漏的场景 如果您预先知道什么地方可能出错,那么您就能够小心避免陷

const int *p和int * const p的区别(常量指针与指向常量的指针) .

  对于指针和常量,有以下三种形式都是正确的: const char * myPtr = &char_A;//指向常量的指针 char * const myPtr = &char_A;//常量的指针 const char * const myPtr = &char_A;//指向常量的常量指针 下面依次对这三种类型进行介绍. 因为*操作符是左操作符,左操作符的优先级是从右到左,对于 1.常量指针(Constant Pointers) int * const p 先看const再看*

深入const int *p与int * const p的区别详解(常量指针与指向常量的指针)_C 语言

对于指针和常量,有以下三种形式都是正确的: 复制代码 代码如下: const char * myPtr = &char_A;//指向常量的指针char * const myPtr = &char_A;//常量的指针const char * const myPtr = &char_A;//指向常量的常量指针 下面依次对这三种类型进行介绍.因为*操作符是左操作符,左操作符的优先级是从右到左,对于1.常量指针(Constant Pointers) 复制代码 代码如下: int * con

了解 C 语言中的指针和内存泄漏及如何避免

如棵你在使用 C 语言时,厌倦花时间调试指针和内存泄漏问题,那么本文将带您了解可能导致内存破坏的指针操作类型,您还将研究一些场景,了解要在使用动态内存分配时考虑什么问题. 引言 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具. 本文将与您分享开发人员在开始使用指针

&lt;font color=&quot;red&quot;&gt;[置顶]&lt;/font&gt;

Profile Introduction to Blog 您能看到这篇博客导读是我的荣幸,本博客会持续更新,感谢您的支持,欢迎您的关注与留言.博客有多个专栏,分别是关于 Windows App开发 . UWP(通用Windows平台)开发 . SICP习题解 和 Scheme语言学习 . 算法解析 与 LeetCode等题解 . Android应用开发 ,而最近会添加的文章将主要是算法和Android,不过其它内容也会继续完善. About the Author 独立 Windows App 和

【软妹带你学技术】Duang!C++那些不得不说的事儿

艾瑞宝迪看过来!(偷偷唱起来了什么鬼......)话说今天,阳光明媚风景如画,正是畅所欲言夸夸其谈的好日子哇,所以,咱们聊聊C++可否?品一杯茶,执一支笔,45°仰望沉思(很好,装叉技能开启).所谓C++,那可是编程语言中的大大大大咖,无人不知无人不晓,放之四海Duang力无敌.然而,还是有一些不得不说的事儿需要告知各位兄台,请耐下心来听我细细道来. [C++注意事项一]数据类型及类型转换 本篇中咱们讨论如何选择类型和类型转换的问题. 如何选择类型呢? 1.当数值不可能为负时,选择无符号类型:

如何看待C++

摘自<Effective C++>第一条条款. 今天的 C++ 已经是个多重范型编程语言 (multiparadigm programming language) ,一个同时支持过程形式(procedural) .面向对象形式(object-oriented) 函数形式(functional) .泛型形式 (generic) .元编程形式(metaprogramming ) 的语言.这些能力和弹性使 C++ 成为一个无可匹敌的工具,但也可能引发某些迷 惑:所有"适当用法"似