c/c++易错知识点3(引用和指针)(二)

1.内存访问违规

#include <iostream>
using namespace std;

int main()
{
      char a;
      char *str1=&a;
      char*str2="AAA";
      
      strcpy(str1,"hello");
      cout<<str1<<endl;
      str2[0]='B';
      cout<<str1<<endl;

      return 0;
}

str1指向一个字节大小的内存区。由于复制“hello”字符串最少需要6个字节,显然内存大小不够。因此会因为越界进行内存读写而导致程序崩溃。

str2指向“AAA”这个字符串常量。因为是常量,所以对str2[0]的赋值操作是不合法的。


2.指针的隐式转换

#include <stdio.h>

int main()
{
     int ival=1024;
     int ival2=2048;
     int *pi1=&ival;
     int *pi2=&ival2;
     int **pi3=0;

     ival =*pi3;
     *pi2=*pi3;
     ival =pi2;
     pi2=*pi1;
     pi1=*pi3;
     ival=*pi1;
     pi1=ival;
     pi3=&pi2;
}

ival=*pi3编译错误,ival为int型,*pi3为int*型,不能隐式转换。

*pi2=*pi3编译错误,*pi2为int型,*pi3为int*型,不能隐式转换。

ival=pi2编译错误,ival是int型,pi2是int*型,不能隐式转换。

pi2=*pi1编译错误,pi2是int*型,*pi1是int型,不能隐式转换。

pi1=*pi3运行错误,pi3是NULL指针,试图得到*pi3的值会发生运行错误。

pi1=ival编译错误,pi1是int*类型,ival是int类型,不能隐式转换。



3.指针常量与常量指针的区别

常量指针就是指向常量的指针,它所指向的地址的内容是不可修改的。const int* p或int const *p

指针常量就是指针的常量,它是不可改变地址的指针,但是可以对它指向的内容进行修改。int * const p



4.指针的区别

char * const p1;
char const * p2;
const char *p3;
const char * const p4;

p1:指针常量,本身不可修改,内容可以修改

p2:常量指针,本身可以修改,内容不可修改

p3:常量指针,本身可以修改,内容不可修改

p4:常量,不可修改内容


5.this指针

下列关于this指针的叙述中,正确的是(D)

A.任何与类相关的函数都有this指针

B,类的成员函数都有this指针

C.类的友元函数都有this指针

D,类的非静态成员函数才有this指针

*A错误。类的非静态成员函数是属于类的对象,含有this指针。而类的static函数属于类本身,不含this指针。

*B错误。类的非静态成员函数是属于类的对象,含有this指针。而类的static函数属于类本身,不含this指针。

*C错误。友元函数是非成员函数,所以它无法通过this指针获得一份拷贝。


对于类成员函数而言,并不是一个对象对应一个单独的成员函数体,而是此类的所有的对象共用这个成员函数体。当程序被编译之后,此成员函数地址即已确定。我们常说,调用类成员函数时,会将当前对象的this指针传给成员函数。没错,一个类的成员函数体只有一份,而成员函数之所以能把属于此类的各个对象的数据区别开,就在于每次执行类成员函数时,都会把当前对象的this指针(对象首地址)传入成员函数,函数体内所有对类数据成员的访问,都会被转化为this->数据成员的方式。

如果函数里没有访问对象的任何数据成员,那么此时传进来的对象this指针实际上是没有任何用处的。这样的函数,其特征与全局函数并没有太大区别。


6.指针数组与数组指针的区别

int* a[4]     指针数组     

                 表示:数组a中的元素都为int型指针    

                 元素表示:*a[i]   *(a[i])是一样的,因为[]优先级高于*

int (*a)[4]   数组指针     

                 表示:指向数组a的指针

                 元素表示:(*a)[i]  


#include <stdio.h>

int main()
{
    char *str[]={"welcome","to","Fortemedia","nanjing"};
char **p=str+1;
str[0]=(*p++)+2;
str[1]=*(p+1);
str[2]=p[1]+3;
str[3]=p[0]+(str[2]-str[1]);
printf("%s\n",str[0]);
printf("%s\n",str[1]);
printf("%s\n",str[2]);
printf("%s\n",str[3]);

return 0;
}

输出结果为:空;nanjing;jing;g


7.野指针的成因

(1)指针没有被初始化

(2)指针p被free或delete后,没有置为NULL


8.有了molloc/free,为什么还有new/delete

malloc与free是c/c++的标准库函数,new/delete是c++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能把执行析构函数和析构函数的任务强加于malloc/free,因此只有使用new/delete运算符。


9.动态内存的传递

可以用三种方法解决动态内存传递的问题

(1)在c语言中,可以通过采用指向指针的指针解决这个问题,可以把str的地址传给函数。

(2)在c++中,多了一种选择,就是传递str指针的引用。

(3)使用函数返回值来传递动态内存。 


10.内存分配的几种方式

(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,例如全局变量。

(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,处理器的指令集中有关于栈内存的分配运算,因此效率很高,但是分配的内存容量有限。

(3)从堆上分配,亦称为动态内存分配。程序在运行时用malloc或new中申请任意多少的内存,自己负责何时用free或delete释放。灵活但问题也多。



11.句柄和指针的区别

(1)句柄所指的可以是一个很复杂的结构,并且很有可能是与系统有关的。比如说线程的句柄,它指向的就是一个类或者结构,它和系统有很密切的关系。当一个线程由于不可预料的原因而终止时,系统就可以返回它所占用的资料,如 CPU、内存等。反过来想可以知道,这个句柄中的某一些项是与系统进行交互的。由于Windows系统是一个多任务的系统,它随时都可能分配内存、回收内存、重组内存。

(2)指针也可以指向一个复杂结构,但是通常是由用户定义的,所以必需的工作都要用户完成,特别是删除的时候。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值