在构造函数中使用new时应注意的事项
在构造函数中使用new时应注意的事项
使用new初始化对象的指针成员时必须特别小心。
● 如果在构造函数中使用new来初始化指针成员,则应该在析构函数中使用delete。
● new和delete必须相互兼容。new对应于delete,new[]对应于delete[]。
● 如果有多个析构函数,则必须以相同的方式使用new,要么都带中括号,要么都不带。因为只有一个析构函数,所有的构造函数都必须与它兼容。然而,可以在一个构造函数中使用new初始化指针,而在另一个构造函数中将指针初始化为空,这是因为delete(无论是带中括号还是不带中括号)可以用于空指针。
● 应定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象。
String::String(const String &st)
{num_strings++; //如果需要,则处理静态成员更新len = st.len; //复制字符串相同长度str = new char[len + 1]; //分配空间strcpy(str, st.str); //复制字符串给新的地址
}
复制构造函数应分配足够的空间来存储复制的数据,并复制数据,而不仅仅是数据的地址,还应该更新所有受影响的静态类成员。
● 应当定义一个赋值运算符,通过深度复制将一个对象复制给另一个对象。
String & String::operator=(const String &st)
{if (this == &st) //分配对象给它本身return *this;delete[] str; //释放以前的字符串len = st.len; str = new char[len + 1]; //获得空间给新的字符串strcpy(str, st.str); //复制字符串return *this; //返回调用对象的引用
}
检查自我赋值的情况,释放成员指针以前指向的内存,复制数据而不仅仅是数据的地址,并返回一个指向调用对象的引用。
应该和不应该
下面的摘要包含了两个不正确的示例,和一个良好的构造函数示例:
String::String()
{str = "default string"; //没有new[]len = std::strlen(str);
}String::String(const char* s)
{len = std::strlen(s);str = new char; //没有[]std::strcpy(str, s); //没有申请空间
}String::String(const String &st)
{len = st.len;str = new char[len+1]; //分片空间std::strcpy(str, st.str); //拷贝值
}
第一个构造函数没有使用new来初始化str。对默认对象调用析构函数时,析构函数使用delete来释放str。对不是使用new初始化的指针使用delete时,结果将是不确定的,并可能有害的。可将该构造函数修改为下面的任何一种形式:
String::String()
{len = 0;str = new char[1]; //利用new和[]str[0] = '\0';
}String::String()
{len = 0;str = 0; //C++11 str=nullptr
}String::String()
{static const char* s = "C++"; //初始化仅一次len = std::strlen(s);str = new char[len+1]; //利用new和[]std::strcpy(str, s);
}
第二个构造函数使用了new,但分配的内存量不正确。因此,new返回的内存块只能保存一个字符。试图将过长的字符串复制到该内存单元中,将导致内存问题。另外,这里使用的new不带中括号,这与另一个构造函数的正确格式不一致。
第三个构造函数正确。
最后,下面的析构函数无法与前面的构造函数正常地协同工作:
String::~String()
{ delete str; //应该delete[]str;
}
该析构函数未能正确使用delete。由于构造函数创建的是一个字符数组,因此析构函数应该删除一个数组。
包含类成员的类的逐成员复制
假设类成员的类型为String类或标准string类:
class Magazine
{private:String title;string publisher;
...
};
String和string都使用动态内存分配,但这不意味着需要为Magazine类编写复制构造函数和赋值运算符。
默认的逐成员复制和赋值行为有一定的智能。如果将一个Magazine对象复制或赋值给另一个Magazine对象,逐成员复制将使用成员类型定义的复制构造函数和赋值运算符。
复制成员title时,将使用String的复制构造函数,而将成员title赋给另一个Magazine对象时,将使用String的赋值运算符,依次类推。然后,如果Magazine类因其他成员需要定义复制构造函数和赋值运算符,情况将更复杂:这种情况,这些函数必须显式调用String和string的复制构造函数和赋值运算符。
在构造函数中使用new时应注意的事项相关推荐
- 《淘宝网开店 拍摄 修图 设计 装修 实战150招》一一1.2 选购镜头时应注意的事项...
本节书摘来自异步社区出版社<淘宝网开店 拍摄 修图 设计 装修 实战150招>一书中的第1章,第1.2节,作者: 葛存山,更多章节内容可以访问云栖社区"异步社区"公众号 ...
- chipsel语言_用VHDL语言对FPGA和CPLD器件进行开发时应注意的事项
第25卷第4期苏 州 大 学 学 报(工 科 版)Vol.25No.4 2005年8月JOURNA L OF SOOCH OW UNIVERSIT Y(ENGINEERING SCIENCE E DI ...
- 系统技术方案 系统构架_构架系统时应注意的事项
系统技术方案 系统构架 by Ayelet Sachto 通过Ayelet Sachto 架构系统时要记住的6件事 (6 Things to keep in mind when architectin ...
- 资产模型数据初始化时应注意的事项
资产模型建立之后,在数据初始化上有个比较特殊的地方,需要激活一个BADI,然后按顺序初始化数据. 1. 要AA11和AA12保证抽数时的增量提取间隔和总账行一致. 2. 数据抽 ...
- 使用和调整电磁铁时应注意的事项
运用和调整电磁铁应留意以下几点: (1).设备电磁铁从前,应翻开接线盒的盖子,打扫内部的尘土.假设电磁铁长时间储存未用,在应用设备前应进行干燥. (2).有衔铁的电磁铁应通电几回,以查看衔铁动作是否灵 ...
- 构造函数中不应调用虚函数
今天调试程序,遇到一个很费解的问题,现在做个记录: class CS3Adapter : public CBaseAdapter 类CS3Adapter继承于CBaseAdapter,其中 CBase ...
- 【电气专业知识问答】问:电流互感器在运行中为什么要严防二次侧开路,电压互感器则要严防二次侧短路?发生电流互感器开路和电压互感器短路时应如何处理?
[电气专业知识问答] 问:电流互感器在运行中为什么要严防二次侧开路,电压互感器则要严防二次侧短路?发生电流互感器开路和电压互感器短路时应如何处理? 答:(1)电压互感器是一个内阻极小的电压源,正常运行 ...
- 构造函数中的虚拟成员调用
我从ReSharper得到警告,关于从对象构造函数调用虚拟成员的信息. 为什么这不是要做的事情? #1楼 因为在构造函数完成执行之前,对象没有完全实例化. 虚函数引用的任何成员都不得初始化. 在C + ...
- php构造函数里抛出异常_php-在类的构造函数中返回值
php-在类的构造函数中返回值 到目前为止,我有一个带有构造函数的29447791671682017201728类 public function __construct ($identifier = ...
最新文章
- glibc降级后怎么恢复 linux_Linux(CentOS)GLIBC出错补救方式
- 提高ADO性能的优秀经验
- gridview、datalist、repeater、FormView、DetailsView的区别详解
- ADSL获取的IP地址与网关相同,却能上网的原理
- CVPR 2020 | 反传统的无监督人脸旋转方案:旋转-渲染
- Java 运行时数据区域
- 「JupyterNotebook」Jupyter快捷键个人笔记
- g20曲线拟合源码解读
- “美登杯”上海市高校大学生程序设计邀请赛 **D. 小花梨的取石子游戏**
- uC/OS-II源码分析(总体思路一)(
- 字符串之将整数字符串转成整数值
- OpenCV3.4.5带GPU编译error: #error This file requires compiler and library support for the ISO C++ 2011
- ps查看所有php进程,ps命令就是最基本进程查看命令
- Android Animation --ScaleAnimation
- LeetCode:Balanced Binary Tree
- (46)Xilinx ILA IP核配置(七)(第10天)
- 陕西师范大学远程教育学院计算机应用基础,陕西师范大学远程教育学院计算机应用基础机考备考试题.doc...
- 堆排序(超详细图解 java版)
- 设计模式之依赖倒置原则
- 盛大如何再次“盛大”
热门文章
- x270 运行linux,Deepin15.7已成功安装至落魄的ThinkPad X270
- mysql udf禁用_如何禁用 mysql 的 udf 功能
- MFC初步教程(三):菜单
- 【并行计算-CUDA开发】关于共享内存(shared memory)和存储体(bank)的事实和疑惑...
- asp.net 模板页中 控件 ID和Name 的变化
- 计算机网络---UDP协议与TCP协议
- html页面获取时间格式,js实现动态获取系统时间,显示到页面上
- i3处理器_英特尔低端霸主酷睿I3处理器又降10元!机器怎么配?为粉丝答疑
- 理财产品利息一直降低是什么原因?
- 两百多的无线蓝牙耳机和一千多的AirPods,外观几乎一样,硬件差距在哪里?