[计算机]如何理解拷贝构造函数

上传人:豆浆 文档编号:33377789 上传时间:2018-02-15 格式:DOC 页数:6 大小:50.50KB
返回 下载 相关 举报
[计算机]如何理解拷贝构造函数_第1页
第1页 / 共6页
[计算机]如何理解拷贝构造函数_第2页
第2页 / 共6页
[计算机]如何理解拷贝构造函数_第3页
第3页 / 共6页
[计算机]如何理解拷贝构造函数_第4页
第4页 / 共6页
[计算机]如何理解拷贝构造函数_第5页
第5页 / 共6页
点击查看更多>>
资源描述

《[计算机]如何理解拷贝构造函数》由会员分享,可在线阅读,更多相关《[计算机]如何理解拷贝构造函数(6页珍藏版)》请在金锄头文库上搜索。

1、我的心得:对结构和对象的参数传递和函数返回,尽量用引用,不要用值传递,一是可以节省内存开销,二是避免再创造临时对象或结构时,引起错误(特别是包含动态分配成员时)拷贝构造函数拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的参数(对象的引用)是不可变的(const 类型)。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。一 般 来 说 , 调 用 拷 贝 构 造 函 数 的 情 形在 C+中 , 下 面 三 种 对 象 需 要

2、调 用 拷 贝 构 造 函 数 : 1) 一 个 对 象 以 值 传 递 的 方 式 传 入 函 数 体 ; 2) 一 个 对 象 以 值 传 递 的 方 式 从 函 数 返 回 ; 3) 一 个 对 象 需 要 通 过 另 外 一 个 对 象 进 行 初 始 化 ; 如 果 在 前 两 种 情 况 不 使 用 拷 贝 构 造 函 数 的 时 候 , 就 会 导 致 一 个指 针 指 向 已 经 被 删 除 的 内 存 空 间 。 对 于 第 三 种 情 况 来 说 , 初 始 化 和赋 值 的 不 同 含 义 是 构 造 函 数 调 用 的 原 因 。 事 实 上 , 拷 贝 构 造 函 数

3、 是由 普 通 构 造 函 数 和 赋 值 操 作 符 共 同 实 现 的 。 描 述 拷 贝 构 造 函 数 和 赋值 运 算 符 的 异 同 的 参 考 资 料 有 很 多 。 拷 贝 构 造 函 数 不 可 以 改 变 它 所 引 用 的 对 象 , 其 原 因 如 下 : 当 一个 对 象 以 传 递 值 的 方 式 传 一 个 函 数 的 时 候 , 拷 贝 构 造 函 数 自 动 的 被调 用 来 生 成 函 数 中 的 对 象 。 如 果 一 个 对 象 是 被 传 入 自 己 的 拷 贝 构 造函 数 , 它 的 拷 贝 构 造 函 数 将 会 被 调 用 来 拷 贝 这 个

4、对 象 这 样 复 制 才 可以 传 入 它 自 己 的 拷 贝 构 造 函 数 , 这 会 导 致 无 限 循 环 直 至 栈 溢 出( Stack Overflow) 。 除 了 当 对 象 传 入 函 数 的 时 候 被 隐 式 调 用 以 外 ,拷 贝 构 造 函 数 在 对 象 被 函 数 返 回 的 时 候 也 同 样 的 被 调 用 。 隐 式 的 拷 贝 构 造 函 数如 果 在 类 中 没 有 显 式 的 声 明 一 个 拷 贝 构 造 函 数 , 那 么 , 编 译器 会 自 动 生 成 一 个 来 进 行 对 象 之 间 的 位 拷 贝 ( Bitwise Copy) 。

5、这 个 隐 含 的 拷 贝 构 造 函 数 简 单 的 关 联 了 所 有 的 类 成 员 。 注 意 到 这 个隐 式 的 拷 贝 构 造 函 数 和 显 式 声 明 的 拷 贝 构 造 函 数 的 不 同 在 于 对 成 员的 关 联 方 式 。 显 式 声 明 的 拷 贝 构 造 函 数 关 联 的 只 是 被 实 例 化 的 类 成员 的 缺 省 构 造 函 数 , 除 非 另 外 一 个 构 造 函 数 在 类 初 始 化 或 构 造 列 表的 时 候 被 调 用 。 拷 贝 构 造 函 数 使 程 序 更 有 效 率 , 因 为 它 不 用 再 构 造 一 个 对 象 的时 候 改

6、 变 构 造 函 数 的 参 数 列 表 。 设 计 拷 贝 构 造 函 数 是 一 个 良 好 的 风格 , 即 使 是 编 译 系 统 会 自 动 为 你 生 成 默 认 拷 贝 构 造 函 数 。 事 实 上 ,默 认 拷 贝 构 造 函 数 可 以 应 付 许 多 情 况 。 示 例以 下 讨 论 中 将 用 到 的 例 子 : class CExample public: CExample()pBuffer=NULL; nSize=0; CExample()delete pBuffer; void Init(int n) pBuffer=new charn; nSize=n; pri

7、vate: char *pBuffer; /类 的 对 象 中 包 含 指 针 ,指 向 动 态 分 配 的 内存 资 源 int nSize; ; 这 个 类 的 主 要 特 点 是 包 含 指 向 其 他 资 源 的 指 针 。 pBuffer 指 向 堆 中 分 配 的 一 段 内 存 空 间 。 int main(int argc, char* argv) CExample theObjone; theObjone.Init(40); /现 在 需 要 另 一 个 对 象 ,需 要 将 他 初 始 化 成 对 象 一 的 状 态 CExample theObjtwo=theObjone

8、; . 语 句 CExample theObjtwo=theObjone;用 theObjone 初 始 化theObjtwo。 其 完 成 方 式 是 内 存 拷 贝 , 复 制 所 有 成 员 的 值 。 完 成 后 , theObjtwo.pBuffer=theObjone.pBuffer。 即 它 们 将 指 向 同 样 的 地 方 , 指 针 虽 然 复 制 了 , 但 所 指 向 的 空 间并 没 有 复 制 , 而 是 由 两 个 对 象 共 用 了 。 这 样 不 符 合 要 求 , 对 象 之 间不 独 立 了 , 并 为 空 间 的 删 除 带 来 隐 患 。 所 以 需

9、要 采 用 必 要 的 手 段 来避 免 此 类 情 况 。 回 顾 一 下 此 语 句 的 具 体 过 程 :首 先 建 立 对 象 theObjtwo, 并 调用 其 构 造 函 数 , 然 后 成 员 被 拷 贝 。 可 以 在 构 造 函 数 中 添 加 操 作 来 解 决 指 针 成 员 的 问 题 。 所 以 C+语 法 中 除 了 提 供 缺 省 形 式 的 构 造 函 数 外 , 还 规 范 了 另一 种 特 殊 的 构 造 函 数 : 拷 贝 构 造 函 数 , 上 面 的 语 句 中 , 如 果 类 中 定义 了 拷 贝 构 造 函 数 , 这 对 象 建 立 时 , 调

10、用 的 将 是 拷 贝 构 造 函 数 , 在拷 贝 构 造 函 数 中 , 可 以 根 据 传 入 的 变 量 , 复 制 指 针 所 指 向 的 资 源 。 拷 贝 构 造 函 数 的 格 式 为 :构 造 函 数 名 (对 象 的 引 用 ) 提 供 了 拷 贝 构 造 函 数 后 的 CExample 类 定 义 为 : class CExample public: CExample()pBuffer=NULL; nSize=0; CExample()delete pBuffer; CExample(const CExample /拷 贝 构 造 函 数 void Init(int n

11、) pBuffer=new charn; nSize=n; private: char *pBuffer; /类 的 对 象 中 包 含 指 针 ,指 向 动 态 分 配 的 内存 资 源 int nSize; ; CExample:CExample(const CExample& RightSides) /拷 贝构 造 函 数 的 定 义 nSize=RightSides.nSize; /复 制 常 规 成 员 pBuffer=new charnSize; /复 制 指 针 指 向 的 内 容 memcpy(RightSides.pBuffer,pBuffer,nSize*sizeof(ch

12、ar); /构 造 函 数 是 没 有 返 回 值 , 没 有 return 语 句 的这 样 , 定 义 新 对 象 , 并 用 已 有 对 象 初 始 化 新 对 象 时 ,CExample(const CExample& RightSides)将 被 调 用 , 而 已 有 对 象用 别 名 RightSides 传 给 构 造 函 数 , 以 用 来 作 复 制 。 原 则 上 , 应该 为 所 有 包 含 动 态 分 配 成 员 的 类 都 提 供 拷 贝 构 造 函 数 。下 面 介 绍 拷 贝 构 造 函 数 的 另 一 种 调 用 。 当 对 象 直 接 作 为 参 数 传给

13、函 数 时 , 函 数 将 建 立 对 象 的 临 时 拷 贝 , 这 个 拷 贝 过 程 也 将 调 同 拷贝 构 造 函 数 。 例 如 : BOOL testfunc(CExample obj); testfunc(theObjone); /对 象 直 接 作 为 参 数 。 BOOL testfunc(CExample obj) /针 对 obj 的 操 作 实 际 上 是 针 对 复 制 后 的 临 时 拷 贝 进 行 的 还 有 一 种 情 况 , 也 是 与 临 时 对 象 有 关 的 当 函 数 中 的 局 部 对 象 被 返 回 给 函 数 调 者 时 , 也 将 建 立 此

14、 局 部 对象 的 一 个 临 时 拷 贝 , 拷 贝 构 造 函 数 也 将 被 调 用 CTest func() CTest theTest; return theTest; 下 面 的 代 码 与 上 例 相 似 INT MAIN(INT ARGC, CHAR* ARGV) CEXAMPLE THEOBJONE; THEOBJONE.INIT(40); CEXAMPLE THEOBJTHREE; THEOBJTHREE.INIT(60); /现 在 需 要 一 个 对 象 赋 值 操 作 ,被 赋 值 对 象 的 原 内 容 被 清 除 ,并 用 右 边 对 象 的 内 容 填 充 。

15、THEOBJTHREE=THEOBJONE; RETURN 0; 也 用 到 了 =号 , 但 与 一 、 中 的 例 子 并 不 同 , 一 、 的 例 子中 , =在 对 象 声 明 语 句 中 , 表 示 初 始 化 。 更 多 时 候 ,这 种 初 始 化也 可 用 括 号 表 示 。 例 如 CEXAMPLE THEOBJONE(THEOBJTWO); 而 本 例 子 中 , =表 示 赋 值 操 作 。 将 对 象 THEOBJONE 的 内 容 复制 到 对 象 THEOBJTHREE;, 这 其 中 涉 及 到 对 象 THEOBJTHREE 原 有 内容 的 丢 弃 , 新

16、内 容 的 复 制 。 但 =的 缺 省 操 作 只 是 将 成 员 变 量 的 值 相 应 复 制 。 旧 的 值 被 自然 丢 弃 。 由 于 对 象 内 包 含 指 针 , 将 造 成 不 良 后 果 :指 针 的 值 被 丢 弃 了 ,但 指 针 指 向 的 内 容 并 未 释 放 。 指 针 的 值 被 复 制 了 , 但 指 针 所 指 内 容并 未 复 制 。 因 此 , 包 含 动 态 分 配 成 员 的 类 除 提 供 拷 贝 构 造 函数 外 , 还 应 该 考 虑 重 载 =赋 值 操 作 符 号 。 类 定 义 变 为 : CLASS CEXAMPLE . CEXAMPLE(CONST CEXAMPLE /拷 贝 构 造 函 数 CEXAMPLE /赋 值 符

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号