学堂在线C++程序设计第八章学习笔记

学堂在线C++程序设计第八章学习笔记

指针与数组

定义指向数组元素的指针
定义与赋值
例如: int a[10], *pa;
pa = &a[0] 或 pa = &a

*(pa +1)就是 a[1]

也可以 pa[1]

指针数组:数组的元素是指针类型
例如:Point *pa[2];
由pa[0],pa[1]两个指针构成

指针与函数

为什么需要指针做参数

  • 需要数据双向传递时(引用传递也可以达到此效果)
  • 需要传递一组数据,只传首地址运行效率比较高
指针类型的函数

若函数的返回类型是指针类型,该函数就是指针类型的函数

指针函数的定义形式:

存储类型 数据类型 *函数名() {

}
  • 不要将非静态局部地址用作函数的返回值
    • 因为非静态局部地址作用域仅限于函数内部,离开函数就被销毁
int main() {
    int *function();
    int *ptr = function();
    *ptr = 5; //危险!!!
    return 0;
}

int *function() {
    int local = 0; //作用域只在函数内部有效
    return &local; 
} //函数结束,变量local被释放
  • 返回的指针要确保在主调函数中是有效合法的地址

在子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的,但是内存分配释放不在同一级别,要注意不能忘记释放,避免内存泄露

int main() {
    int *function();
    int *ptr = function();
    *ptr = 5; //如果返回的是 new 分配的,就可以了
    delete ptr; //但是这里需要释放,避免内存泄露
    return 0;
}

int *function() {
    int *local = new int(); //new 分配的不会离开函数就释放
    return local; 
} 
指向函数的指针

函数指针的定义

  • 定义形式
    存储类型 数据类型 (*函数指针名)()
  • 含义
    函数指针指向的是程序代码存储区

用途:函数回调

  • 通过函数指针调用的函数
    • 例如将函数的指针作为参赛传递给一个函数,使得在处理相似事件的时候可以灵活的使用不同方法
  • 调用者不关心谁是被调用者
    • 需要知道存在一个具有特定原型和限制条件的被调用函数。
对象指针

定义:
类名 *对象指针名;
例如:

Point a(5,10);
Point *ptr;
ptr = &a;

通过指针访问对象成员
对象指针名->成员名
例如:
ptr->getX() 相当于 (*ptr).getX()

this 指针

  • 隐含于类的每一个非静态成员函数中
  • 指出成员函数所操作的对象
    • 当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含的使用了this指针。
动态内存分配

动态申请内存
new 类型名T (初始化参数列表)

  • 功能:
    在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋值
  • 结果值:
    成功:T类型的指针,指向新分配的内存,失败:抛出异常

释放内存
delete 指针P

  • 功能:
    释放指针P所指向的内存,p必须是new操作符的返回值

智能指针

C++11提供的

  • unique_ptr
    • 不允许多个指针共享资源,可以用标准库中的move函数转移指针
  • shared_ptr
    • 多个指针共享资源
  • weak_ptr
    • 可复制 shared_ptr ,但其构造或者释放对资源不产生影响

Vector

为什么需要Vector

  • 封装任何类型的动态数组,自动创建和删除
  • 数组下标越界检查

定义

  • vector<元素类型> 数组对象名(数组长度);
  • 例子:
    vector arr(5) 建立大小为5的int数组

vector对象的使用

  • 对数组元素的引用
    与普通数组具有相同形式:
    vector对象名[下标表达式]
    vector数组对象名不表示数组首地址
  • 获得数组长度
    size函数
    vector对象名.size()

对象复制和移动

浅层复制

  • 实现对象间数据元素的一一对应复制

深层复制

  • 当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制
申请和释放动态数组

分配和释放动态数组

  • 分配:new 类型名T [数组长度]
    • 数组长度可以是任何整数类型表达式,在运行时计算
  • 释放:delete[] 数组名p
    • 释放指针p所指向的数组
    • p必须是用new分配得到的数组首地址

动态创建多维数组
new 类型名T[第1维长度][第2维长度]

  • 如果内存申请成功,new 运算返回一个指向新分配内存首地址的指针
  • 例如
    char (*fp)[3];
    fp = new char[2][3]

将动态数组封装成类

  • 更加简洁,便于管理
  • 可以在访问数组元素前检查下标是否越界
移动构造

C++11中提供了新的构造方法

C++11之前,如果要将源对象的状态转移到目标对象只能通过复制。在某些情况下,我们没有必要复制对象 – 只需要移动它们

移动构造

  • C++11引入移动语义:
    • 源 对象资源的控制权全部交给目标对象
  • 移动构造函数

移动构造函数
class_name(class_name &&)

字符串

C风格字符串

字符串常量

  • 例如:“program”
  • 各字符连续,顺序存放,每个字符占一个字节,以’\0’结尾,相当于一个隐含创建的字符常量数组
  • “program” 出现在表达式中,表示这个char数组的首地址
  • 首地址可以赋给char常量指针
  • const char *STRING1 = “program”

用字符数组存储字符串

  • 例如
    char str[8] = {‘p’,‘r’,‘o’,‘g’,‘r’,‘a’,‘m’,’\0’}
    char str[8] = “program”
  • 缺点
    • 执行连接,拷贝,比较等操作,都需要显式调用库函数,很麻烦
    • 当字符串长度不确定时,需要用new 动态创建字符数组,最后要用delete释放,很繁琐
    • 字符串实际长度大于为他分配的空间时,会产生数组下标越界的错误
string类

构造函数

  • string() 默认的,建立长度为0的字符串
    例如 string s1;
  • string(const char *s); //用指针s所指向的字符串常量初始化string对象
    例如 string s2 = “abc”;
  • string(const string& rhs); //复制构造函数
    例如 string s3 = s2;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值