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