C++指针和动态内存分配
2015-09-13 20:44 Fururur 阅读(2968) 评论(0) 编辑 收藏 举报指针和动态内存分配
数组与指针
数组
- 数组名是一个指针常量。
- 数组名传递数据时,传递的是地址。
- 数组作为函数参数时不指定第一维大小。
- 对象数组
A a[2] = {A(1,2)};
执行时先调用有参数的构造函数初始化a[0],然后调用默认构造函数初始化a[1]。
指针
- 指向常量的指针 。不能改变所指对象的值,但可以指向其他对象。
int a;
const int* p1 = &a;
int b;
p1 = &b;//正确,可以指向其他对象。
*p1 = 1;//错误,不能改变所指对象的值
- 指针类型的常量 。指针本身的值不能被改变。
int a,b;
int* const p1 = &a;
p1 = &b; //错误,指针本身的值不能被改变
指针数组
int line1[] = {1,0,0};
int line2[] = {0,1,0};
int line3[] = {0,0,1};
int* PLine[] = {line1,line2,line3};
for(int i = 0;i < 3;++i){
for(int j = 0;j < 3;++j)
cout<<PLine[i][j]<<" ";
cout<<endl;
}
函数指针
void foo(int a){
cout<<"cout foo"<<a<<endl;
}
void bar(int b){
cout<<"cout bar"<<b<<endl;
}
int main()
{
void (*ptr)(int);
ptr = foo;
ptr(1);
ptr = bar;
ptr(2);
return 0;
}
对象指针
指向对象的指针
Point* ptr;
Point p1;
ptr = &p1;//指向一个对象
p->getX(); //(*p).getX() 调用相应的成员
this指针
this指针是隐含于每一个类的非静态成员函数中的特殊指针,用于指向正在被成员函数操作的对象。
动态内存分配
一般对象的动态内存分配
在C++中建立和删除堆对象使用的两个操作符:new和delete。
*new操作 *
该语句运行过程中申请分配用于存放指定类型数据的内存空间,并根据初始化参数列表中的值进行初始化。如果内存申请成功,便 返回一个指向新分配内存首地址的类型的指针 。可以通过该指针对堆对象进行访问。如果申请失败则抛出异常。
- 分配基本类型的变量。
int* p = new int; //分配内存后不设初值。
int* p1 = new int();//分配内存后,用0来初始化。
int* p1 = new int(1);
- 分配类类型变量
class Point {
public:
Point():x(0),y(0){
cout<<"Default constructor called."<<endl;
}
Point(int x,int y):x(x),y(y){
cout<<"Constructor called."<<endl;
}
~Point(){cout<<"Destructor called."<<endl;}
private:
int x,y;
};
int main()
{
cout<<"Step one"<<endl;
Point* ptr1 = new Point;//未给出参数列表,调用默认ctor
delete ptr1;//删除对象,调用dtor
cout<<"Step two"<<endl;
ptr1 = new Point(1,2);//给出参数列表,调用有形ctor
delete ptr1;//删除对象,调用dtor
return 0;
}
注意:
- 用new建立一个类类型的变量时,如果该类存在用户定义的默认ctor,则“new T”和“new T()”的效果是相同的。
- 若用户没有定义默认的ctor,使用“new T”创建对象时,会调用系统隐含的ctor;使用“new T()”创建对象时,系统除了执行那些操作外,还会为基本数据类型和指针类型赋0,而且过程是递归的。
delete操作
如果被删除的是对象,对象的析构函数将被调用。用new建立的对象,只能用delete删除一次。
动态数组
一维数组
int* arr = new int[n]; //new T
int* arr = new int [n]() ;//new T()
int* arr = new int [n](1) ;//用1初始化。
delete[] arr;//删除整个数组。
多维数组的分配
/*
new 类型名T[第一维][第二维]…
分配一个2*3*4的三位数组的两种方法。
1.整个分配,释放的时候是整个释放掉。
2.一层一层分配,释放的时候也是从内而外一层一层释放。
*/
int(*cp)[3][4];
cp = new int [2][3][4]();
delete cp;
//分配空间
int*** p = new int**[2];
for(int i = 0;i < 2; ++i){
p[i] = new int*[3];
for(int j = 0;j < 3; ++j)
p[i][j] = new int[4]();
}
//赋值
for(int i = 0;i < 2; ++i)
for(int j = 0;j < 3; ++j)
for(int k = 0;k < 4; ++k)
p[i][j][k] = i*j*k;
//释放空间
for(int i = 0;i < 2; ++i){
for(int j = 0;j < 3; ++j)
delete[] p[i][j];
delete[] p[i];
}
delete[] p;
深拷贝和浅拷贝
隐含的拷贝构造函数完成的是浅拷贝。
浅拷贝与深拷贝的区别如图。
class Point{
...
};
class ArrayOfPoint{
public:
ArrayOfPoint(const ArrayOfPoint& v);
private:
Point* points;
int size;
};
ArrayOfPoint::ArrayOfPoint(const ArrayOfPoint& v)
{
//深拷贝,为新的对象重新开辟一片内存空间。
size = v.size;
points = new Point[size];
for(int i = 0;i < size; ++i)
points[i] = v.points[i];
}
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载,演绎或用于商业目的,但是必须保留本文的署名Fururur(包含链接),如您有任何疑问或者授权方面的协商,请给我留言。