在构造函数中使用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时应注意的事项相关推荐

  1. 《淘宝网开店 拍摄 修图 设计 装修 实战150招》一一1.2 选购镜头时应注意的事项...

    本节书摘来自异步社区出版社<淘宝网开店 拍摄 修图 设计 装修 实战150招>一书中的第1章,第1.2节,作者: 葛存山,更多章节内容可以访问云栖社区"异步社区"公众号 ...

  2. chipsel语言_用VHDL语言对FPGA和CPLD器件进行开发时应注意的事项

    第25卷第4期苏 州 大 学 学 报(工 科 版)Vol.25No.4 2005年8月JOURNA L OF SOOCH OW UNIVERSIT Y(ENGINEERING SCIENCE E DI ...

  3. 系统技术方案 系统构架_构架系统时应注意的事项

    系统技术方案 系统构架 by Ayelet Sachto 通过Ayelet Sachto 架构系统时要记住的6件事 (6 Things to keep in mind when architectin ...

  4. 资产模型数据初始化时应注意的事项

    资产模型建立之后,在数据初始化上有个比较特殊的地方,需要激活一个BADI,然后按顺序初始化数据. 1.       要AA11和AA12保证抽数时的增量提取间隔和总账行一致. 2.       数据抽 ...

  5. 使用和调整电磁铁时应注意的事项

    运用和调整电磁铁应留意以下几点: (1).设备电磁铁从前,应翻开接线盒的盖子,打扫内部的尘土.假设电磁铁长时间储存未用,在应用设备前应进行干燥. (2).有衔铁的电磁铁应通电几回,以查看衔铁动作是否灵 ...

  6. 构造函数中不应调用虚函数

    今天调试程序,遇到一个很费解的问题,现在做个记录: class CS3Adapter : public CBaseAdapter 类CS3Adapter继承于CBaseAdapter,其中 CBase ...

  7. 【电气专业知识问答】问:电流互感器在运行中为什么要严防二次侧开路,电压互感器则要严防二次侧短路?发生电流互感器开路和电压互感器短路时应如何处理?

    [电气专业知识问答] 问:电流互感器在运行中为什么要严防二次侧开路,电压互感器则要严防二次侧短路?发生电流互感器开路和电压互感器短路时应如何处理? 答:(1)电压互感器是一个内阻极小的电压源,正常运行 ...

  8. 构造函数中的虚拟成员调用

    我从ReSharper得到警告,关于从对象构造函数调用虚拟成员的信息. 为什么这不是要做的事情? #1楼 因为在构造函数完成执行之前,对象没有完全实例化. 虚函数引用的任何成员都不得初始化. 在C + ...

  9. php构造函数里抛出异常_php-在类的构造函数中返回值

    php-在类的构造函数中返回值 到目前为止,我有一个带有构造函数的29447791671682017201728类 public function __construct ($identifier = ...

最新文章

  1. glibc降级后怎么恢复 linux_Linux(CentOS)GLIBC出错补救方式
  2. 提高ADO性能的优秀经验
  3. gridview、datalist、repeater、FormView、DetailsView的区别详解
  4. ADSL获取的IP地址与网关相同,却能上网的原理
  5. CVPR 2020 | 反传统的无监督人脸旋转方案:旋转-渲染
  6. Java 运行时数据区域
  7. 「JupyterNotebook」Jupyter快捷键个人笔记
  8. g20曲线拟合源码解读
  9. “美登杯”上海市高校大学生程序设计邀请赛 **D. 小花梨的取石子游戏**
  10. uC/OS-II源码分析(总体思路一)(
  11. 字符串之将整数字符串转成整数值
  12. OpenCV3.4.5带GPU编译error: #error This file requires compiler and library support for the ISO C++ 2011
  13. ps查看所有php进程,ps命令就是最基本进程查看命令
  14. Android Animation --ScaleAnimation
  15. LeetCode:Balanced Binary Tree
  16. (46)Xilinx ILA IP核配置(七)(第10天)
  17. 陕西师范大学远程教育学院计算机应用基础,陕西师范大学远程教育学院计算机应用基础机考备考试题.doc...
  18. 堆排序(超详细图解 java版)
  19. 设计模式之依赖倒置原则
  20. 盛大如何再次“盛大”

热门文章

  1. x270 运行linux,Deepin15.7已成功安装至落魄的ThinkPad X270
  2. mysql udf禁用_如何禁用 mysql 的 udf 功能
  3. MFC初步教程(三):菜单
  4. 【并行计算-CUDA开发】关于共享内存(shared memory)和存储体(bank)的事实和疑惑...
  5. asp.net 模板页中 控件 ID和Name 的变化
  6. 计算机网络---UDP协议与TCP协议
  7. html页面获取时间格式,js实现动态获取系统时间,显示到页面上
  8. i3处理器_英特尔低端霸主酷睿I3处理器又降10元!机器怎么配?为粉丝答疑
  9. 理财产品利息一直降低是什么原因?
  10. 两百多的无线蓝牙耳机和一千多的AirPods,外观几乎一样,硬件差距在哪里?