QT:库和智能指针

QT:库和智能指针

一、QT 连接数据库

1.1 QT 将数据库分为三个层次

1.1.1 数据库驱动
层:QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin
1.1.2 SQL 接口
层:QSqlDatabase、QSqlQuery、QSqlRecord、QSqlError
1.1.3 用户接口层
型:QSQLQueryModel、QSqlTableModel、QSqlRelationalTableModel

1.2 实现数据库操作的相关方法

1.2.1 添加数据库:
[static] QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver *driver,const QString &connectionName = QLatin1String(defaultConnection))
(QSQLITE SQLite version 3 or above)
1.2.2 设置数据库名称:
void QSqlDatabase::setDatabaseName(const QString &name)
1.2.3 包含数据库:
bool QSqlDatabase::contains(const QString &connectionName = QLatin1String(defaultConnection)
1.2.4 打开数据库:
bool QSqlDriver::open(const QString &db)
1.2.5 关闭数据库:
void QSqlDatabase::close()
1.2.6 错误信息:
QSqlError QSqlDatabase::lastError()
1.2.7 sql语句执行:

构造一个QSqlQuery类对象,调用其成员函数exec,执行sql语句:

bool QSqlQuery::exec(const QString &query)
1.2.8 遍历查询结果的函数:
bool QSqlQuery::next()

1.3 通过数据库实现学生管理系统

1.3.1 头文件

1.3.2 源文件

二、智能指针

2.1 引入背景

  1. C++中在堆区申请空间和释放空间需要使用 new 和 delete 完成
  2. 多个指针指向同一个内存空间,释放其中一个的空间,另一个还在继续使用(悬空指针)
  3. 只是申请了内存空间,使用后忘记释放内存空间,堆区对象没有得到析构
  4. 栈区申请的对象空间,在脱离对象空间后,会自动调用析构函数完成资源的回收,但是堆区的不会自动释放
  5. 总结:上述例子中,在堆区申请一个对象空间,但是没有手动释放空间,造成对象没有析构,为了保证堆区空间使用的安全性,所以引入了智能指针,目的是更加安全的使用堆区空间

2.2 相关概念

  1. C++11 标准提供了两种智能指针,分别是uniquie_ptr(独占智能指针)、shared_ptr(共享智能指针)
  2. 除了上述两种指针外,华友auto_ptr(自动智能指针,已弃用)、weak_ptr(弱智能指针,辅助shared_ptr使用)
  3. 以上所有智能指针都在头文件:#include中
  4. 智能指针是类模板,在栈区创建智能指针对象
  5. 把普通指针交给智能指针管理
  6. 智能指针对象过期时,析构函数会自动释放智能指针管理的指针空间

2.3 独占智能指针(unique_ptr)

2.3.1 独占智能指针概述

独占智能指针会“拥有”它所指向的对象,某一时刻,只能有一个unique_ptr指向给定的对象,当该指针被销毁时,指向的对象也会随之释放。

2.3.2 类的原型
2.3.3 初始化
2.3.4 独占智能指针的注意事项
  1. 重载的*和->运算符,所以可以跟像使用普通指针一样使用该智能指针
  2. 不支持拷贝构造函数和拷贝赋值函数
  3. 不要使用一个原始指针初始化多个unique_ptr
  4. get() 函数可以返回该智能指针的原始指针
  5. 不要使用uniquie_ptr指向非new申请的空间
  6. 有智能指针指向原始指针后,就不要再用原始指针手动释放了
  7. 智能指针作为函数参数传递时,传递引用,不要传递值,因为智能指针没有拷贝构造函数
  8. 智能指针不支持:+、-、++、–
2.3.5 智能指针的更多技巧
  1. 将一个智能指针 unique_ptr 赋值给另一个指针时,可以赋值右值(移动构造存在),但是不能赋值左值(拷贝构造不存在)
  2. 使用 nullptr 给 unique_ptr 赋值时,会自动释放对象
  3. 使用 release() 函数的指针,可以释放 unique_ptr 的指针,并且将原指针返回
  4. std::move 函数,可以转移原始指针的控制权,本质上调用的时候移动构造函数
  5. reset() 函数释放对象
  6. swap() 函数交换两个 unique_ptr 的使用权
  7. unique_ptr 也可以有原始指针的特性,当指向一个继承体系内的基类对象时,也有多态的特性,如同原派生类对象一样
  8. 独占智能指针(unique_ptr)也不是绝对安全的,当程序内有exit() 退出程序时,全局智能指针会释放空间,但是局部智能指针不会
  9. unique_ptr 提供了支持数组的具体化版本,重载了[] 运算符,返回的是引用,可以作为左值使用

2.4 共享智能指针(shared_ptr)

2.4.1 共享智能指针的概述
  1. shared_ptr 共享它指向的对象,多个共享指针可以指向(关联)相同的对象,在内部采用计数器机制来实现
  2. 当新的 shared_ptr 与对象关联时,引用计数器增加1
  3. 当 shared_ptr 超出作用域时,引用计数器减1,当引用计数器变为0时,则表示没有
  4. 任何 shared_ptr 与对象关联,则释放该对象
2.4.2 基本使用
2.4.2.1 初始化
2.4.2.2 使用方法
  1. 智能指针重载了*和-> 操作符,可以像使用原始指针一样使用 shared_ptr
  2. use_count() 函数返回引用计数器的个数
  3. unique() 函数,如果 use_count() 为1,则返回true,否则返回false
  4. 支持普通的拷贝和赋值,左值的 shared_ptr 的计数器减1,右值的 shared_ptr 的计数器将加1,left=right;
  5. get() 函数返回原始指针
  6. 不要用同一个原始指针去初始化多个 shared_ptr
  7. 不要使用 shared_ptr 管理不是new分配的空间内存
  8. 智能指针作为函数参数传递时,传递引用,不要传递值,因为智能指针没有拷贝构造函数
  9. 不支持指针的运算:+、-、++、–
2.4.3 共享智能指针的注意事项
  1. 使用 nullptr 给 shared_ptr 赋值时,将计数器减1,如果计数器为0,释放对象资源,空的 shared_ptr = nullptr;
  2. str::move() 可以转移对原始指针的控制权,还可以将uniquie_ptr转变成 shared_ptr
  3. reset() 改变与资源的关联关系
  4. swap() 函数交换两个 shared_ptr 的控制权
  5. shared_ptr 也可以有原始指针的特性,当指向一个继承体系内的基类对象时,也有多态的特性,如同原派生类对象一样
  6. . 共享智能指针(shared_ptr)也不是绝对安全的,当程序内有exit() 退出程序时,全局智能 shared_ptr 会释放空间,但是局部智能指针不会 shared_ptr 不会释放
  7. shared_ptr 提供了支持数组的具体化版本,重载了[] 运算符,返回的是引用,可以作为左值使用
  8. shared_ptr 的线程安全性:shared_ptr 的引用计数器是线程安全的(引用计数器是原子操作)。多个线程同时读取一个shared_ptr对象是线程安全的;多个线程同时对同一个shared_ptr 对象进行读和写,则需要加锁;多线程读写shared_ptr 所指向的同一对象,不管是相同的shared_ptr对象还是不同的shared_ptr 对象,都要加锁进行保护
  9. 实际开发过程中,unique_ptr 能解决的问题,就尽量不要使用shared_ptr,因为unique_ptr 的效率更高,所用资源更少

2.5 智能指针的删除器

在默认情况下,智能指针过期的时候,用delete 原始指针 方式释放管理的资源的行为、删除器可以是全局函数、仿函数以及 Lambda 表达式,形参为原始指针

2.6 弱智能指针(weak_ptr)

2.6.1 引入目的

shared_ptr 内部维护了一个共享的引用计数器,多个shared_ptr 可以指向同一个资源,如果出现了循环引用的情况,引用计数器将永远无法归零,资源不会被释放

2.6.2 weak_ptr 是什么
  1. weak_ptr 是为了配合 shared_ptr 而引入的,它指向一个由 shared_ptr 管理的资源但不影响资源的生命周期。也就是说,将一个 weak_ptr 绑定到一个 shared_ptr 不会改变 shared_ptr 的引用计数。
  2. 不论是否有 weak_ptr 指向,如果最后一个指向资源的 shared_ptr 被销毁,资源就会被释放。
  3. weak_ptr 更像是 shared_ptr 的助手而不是智能指针。
2.6.3 如何使用 weak_ptr
  1. weiak_ptr 没有重载 -> 和 * 运算符,不能直接访问资源
  2. operator=();把shared_ptr 或 weak_ptr 赋值给 weak_ptr
  3. expired();判断它指向的资源释放已经过期
  4. lock();返回 shared_ptr,如果资源已经过期,返回空的 shared_ptr
  5. reset();将当前的 weak_ptr 置空
  6. swap();交换
  7. weak_ptr 不控制对象的生命周期,但是,它指定对象释放还活着,用lock()函数可以把它提升为 shared_ptr。如果对象还活着,返回有效的shared_ptr,如果对象已经死了,提升会失败,返回一个空的 shared_ptr。提升的行为是线程安全的

2.7 weak_ptr 的使用

2.7.1 单线程可用,多线程不安全版本
2.7.2 多线程安全版本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值