C++指针和动态内存分配

时间:2022-12-14 11:50:52

指针和动态内存分配

数组与指针

数组

  • 数组名是一个指针常量。
  • 数组名传递数据时,传递的是地址。
  • 数组作为函数参数时不指定第一维大小。
  • 对象数组

A a[2] = {A(1,2)};

执行时先调用有参数的构造函数初始化a[0],然后调用默认构造函数初始化a[1]。

指针

  1. 指向常量的指针 。不能改变所指对象的值,但可以指向其他对象。
    int a;
const int* p1 = &a;
int b;
p1 = &b;//正确,可以指向其他对象。
*p1 = 1;//错误,不能改变所指对象的值
  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;
}

注意:

  1. 用new建立一个类类型的变量时,如果该类存在用户定义的默认ctor,则“new T”和“new T()”的效果是相同的。
  2. 若用户没有定义默认的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;

深拷贝和浅拷贝

隐含的拷贝构造函数完成的是浅拷贝。

浅拷贝与深拷贝的区别如图。

C++指针和动态内存分配

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];
}

C++指针和动态内存分配的更多相关文章

  1. 数据结构基础——指针及动态内存分配&lpar;malloc&rpar;

    一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...

  2. c&plus;&plus; 动态数组,指针与动态内存分配

    教学内容: 内存的使用 动态内存分配malloc函数 分配内存时使用sizeof运算符 用指针访问内存 以数组的形式访问内存 一.内存的使用 堆(heap) 在程序执行期间分配内存时,内存区域中的这个 ...

  3. C&plus;&plus;学习 之 指针及动态内存分配(笔记)

    1. 指针 1.1 指针的含义: 简单来说,指针是存储内存地址的变量.当我们声明了一个指针变量后,使用该指针时系统会根据指针内的地址索引内存块,读取内存内的值.指针因为是用来存地址的,所以一般固定长度 ...

  4. C&plus;&plus;二维数组动态内存分配

    对于二维数组和二维指针的内存的分配 这里首选说一下一维指针和一维数组的内存分配情况. 一维: 数组:形如int  a[5];这里定义了一个一维数组a,并且数组的元素个数是5,这里的a是这五个元素的整体 ...

  5. C和指针 第十一章 动态内存分配

    声明数组时,必须指定数组长度,才可以编译,但是如果需要在运行时,指定数组的长度的话,那么就需要动态的分配内存. C函数库stdlib.h提供了两个函数,malloc和free,分别用于执行动态内存分配 ...

  6. 《C和指针》 读书笔记 -- 第11章 动态内存分配

    1.C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和释放,这些函数维护一个可用内存池. void *malloc(size_t size);//返回指向分配的内存块起始位置的 ...

  7. C动态内存分配(C与指针实例)

    主要初步介绍malloc.free.calloc.realloc的基本.日后会有更详细的内容. malloc.free分别用于动态内存分配和释放. malloc会从内存池里提取一块合适的内存(连续的) ...

  8. C&plus;&plus;学习笔记(十一):void&ast;指针、类型转换和动态内存分配

    void*指针 void关键字表示“空类型”的概念.但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西. void ...

  9. C和C指针小记&lpar;十六&rpar;-动态内存分配

    动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...

随机推荐

  1. Project Euler欧拉计划

    1 If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. Th ...

  2. 【C&num;】C&num;容易忽视的错误

    1.string 拼接站内存,前提是字符串比较多的时候string 字符串类型拼接占内存,解决方法就是用 StringBuilder和String.Format2.不知道内置的验证数据类型的方法. ; ...

  3. 【原创】Django-ORM进阶

    基础部分已经写完:[原创]Django-ORM基础 以下部分将对表与表之间的关联操作做以介绍 models.py #_*_coding:utf-8_*_ from django.db import m ...

  4. HtmlParser

    HtmlParser 基本类库使用 HtmlParser 提供了强大的类库来处理 Internet 上的网页,可以实现对网页特定内容的提取和修改.下面通过几个例子来介绍 HtmlParser 的一些使 ...

  5. jdk配置java&lowbar;home的两种方式

    在开发java项目的时候,要先安装jdk,安装完jdk之后我们要配置环境变量.今天说一下java home环境变量. 配置环境变量有两种方式,一种就是在计算机的环境变量里面配置.这个是很简单的.如果你 ...

  6. python&plus;selenium基础之XPATH轴定位&lpar;第二篇&rpar;

    第一篇讲了xpath定位的一些基本定位方法,这里再介绍一种:xpath轴定位,应用场景是当某个元素的各个属性及其组合都不足以定位时,那么可以利用其兄弟节点或者父节点等各种可以定位的元素进行定位. 1. ...

  7. install scala &amp&semi; spark env

    安装Scala 1,到http://www.scala-lang.org/download/ 下载与Spark版本对应的Scala.Spark1.2对应于Scala2.10的版本.这里下载scala- ...

  8. kafka学习指南&lpar;总结版&rpar;

    版本介绍 从使用上来看,以0.9为分界线,0.9开始不再区分高级/低级消费者API. 从兼容性上来看,以0.8.x为分界线,0.8.x不兼容以前的版本. 总体拓扑架构 从上可知: 1.生产者不需要访问 ...

  9. js 获取格林尼治时间戳

    昨天在一论坛里看到有朋友问 js 如何获取格林尼治时间戳.不少朋友第一反应是 toGMTString ...确实可以得到格林尼治时间,但不是时间戳.虽然我也没有啥好的方法一步到位的获取,不过至少是获取 ...

  10. CSS学习摘要-布局

    注:全文摘自MDN-介绍CSS布局 CSS页面布局技术允许我们拾取网页中的元素,并且控制它们相对正常布局流.周边元素.父容器或者主视口/窗口的位置.在这个模块中将涉及更多关于页面布局技术的细节: 浮动 ...