C++语言构造函数与析构函数需要注意的地方。

构造

考虑以下定义

struct Node
{
char *name;
int value;
Node(char *name = "", int value = )
{
name = new char[strlen(name)+];
strcpy(name, name);
value = value;
}
}

声明两个对象

Node node1("child", ), node2(node1);

这行语句创建了两个对象node1,node2,其中node2是用node1的成员进行初始化,现在改变node2成员值

strcpy(node2.name, "parent");
node2.value = ;

打印对象的成员值如下

cout<<node1.name<<' '<<node1.value<<' '<<node2.name<<' '<<node2.value;

结果如下

parent  parent 

问题出在Node结构成员name是一个指针类型,如果结构定义中没有复制构造函数,则编译器使用默认的构造函数,此构造函数在复制值类型与复制指针类型时实现方法不同,复制指针类型时仅仅复制指针的内容(所指向的地址),所以node1和node2的name指针指向了同一个地址。

解决这个问题的办法是自定义一个复制构造函数

struct Node
{
char *name;
int value;
Node(char *name = "", int value = )
{
name = new char[strlen(name)+];
strcpy(name, name);
value = value;
}
Node(const Node& node)
{
name = new char[strlen(node.name) + ];
strcpy(name, node.name);
value = node.value;
}

当然,还有一个类似的问题就是

node2 = node1;

这句代码也是对成员进行浅表复制,解决的办法就是自定义赋值构造函数,仅给出代码片段

Node& operator=(const Node& node)
{
if(this != &n) { // no assignment to itself
if(name != )
delete [] name;  // 注意这里是 delete [],delete只是析构单个对象,而非字符数组
name = new char[strlen(node.name) + ];
strcpy(name, node.name);
value = node.value;
}
return *this;
}

析构

对于以上类型的对象,因为是值类型,所以如果是作为局部变量,当对象处于作用范围之外时将被销毁,被对象占用的内存也会得到释放。然而,这个对象占用的内存虽然被释放,但是跟这个对象相关联的内存则不一定被释放。如上面这个Node类型,有一个指向string的指针成员,因此,销毁Node类型对象时,对象的指针成员(name)所占用的内存被释放(32位机器上指针占用4byte),但是指针指向的string所占用的内存将会变得无法访问,这个内存也就无法被释放了。为了避免这个问题,类(结构)定义中需要包含析构函数。析构函数在对象被销毁时自动被调用,或者主动使用delete关键字调用析构函数。析构函数不接受参数,也不返回值。

在Node的定义增加一个析构函数

~Node()
{
if(name != )
delete [] name;
}

以上讨论了结构(struct)的构造函数和析构函数,对于类(class)的情况类似。

C++构造与析构的更多相关文章

  1. C++浅析——继承类中构造和析构顺序

    先看测试代码,CTEST 继承自CBase,并包含一个CMember成员对象: static int nIndex = 1; class CMember { public: CMember() { p ...

  2. Effective C++ -----条款09:绝不在构造和析构过程中调用virtual函数

    在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).

  3. 【09】绝不在构造和析构过程中调用virtual方法

    1.绝不在构造和析构过程中调用virtual方法,为啥? 原因很简单,对于前者,这种情况下,子类专有成分还没有构造,对于后者,子类专有成分已经销毁,因此调用的并不是子类重写的方法,这不是程序员所期望的 ...

  4. C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)

    这是我的感觉,具体需要研究一下- 找到一篇文章:在构造和析构中抛出异常 测试验证在类构造和析构中抛出异常, 是否会调用该类析构. 如果在一个类成员函数中抛异常, 可以进入该类的析构函数. /// @f ...

  5. STL——空间配置器(构造和析构基本工具)

    以STL的运用角度而言,空间配置器是最不需要介绍的东西,它总是隐藏在一切组件(更具体地说是指容器,container)的背后,默默工作,默默付出.但若以STL的实现角度而言,第一个需要介绍的就是空间配 ...

  6. 魔法方法:构造和析构 - 零基础入门学习Python041

    魔法方法:构造和析构 让编程改变世界 Change the world by program 构造和析构 什么是魔法方法呢?我们来系统总结下: - 魔法方法总是被双下划线包围,例如__init__ - ...

  7. 再探Delphi2010 Class的构造和析构顺序

    发了上一篇博客.盒子上有朋友认为Class的构造和析构延迟加载.是在Unit的初始化后调用的Class的构造.在Unit的反初始化前调用的Class的析构函数. 为了证明一下我又做了个试验 unit ...

  8. Effective C++_笔记_条款09_绝不在构造和析构过程中调用virtual函数

    (整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为方便采用书上的例子,先提出问题,在说解决方案. 1 问题 1: ...

  9. STL—对象的构造与析构

    STL内存空间的配置/释放与对象内容的构造/析构,是分开进行的.   对象的构造.析构         对象的构造由construct函数完成,该函数内部调用定位new运算符,在指定的内存位置构造对象 ...

  10. C++反汇编第二讲,不同作用域下的构造和析构的识别

    C++反汇编第二讲,不同作用域下的构造和析构的识别 目录大纲: 1.全局(静态)对象的识别,(全局静态全局一样的,都是编译期间检查,所以当做全局对象看即可.) 1.1 探究本质,理解构造和析构的生成, ...

随机推荐

  1. JavaEE XML DOM创建之DOM4J

    DOM4J创建xml文档 @author ixenos 1 写出内容到xml文档 XMLWriter writer = new XMLWriter(OutputStream, OutputForamt ...

  2. win7、win8.1淡绿色护眼模式设置

    Win7设置: 右击桌面 -> 个性化 -> 窗口颜色 -> 高级外观设置 选中 -> 项目:窗口     颜色:其他 修改:色调  饱和度 亮度 红  绿  蓝 添加到自定义 ...

  3. linux操作系统简单使用

    文章将包含几个内容: linux简介 linux操作系统的安装简述 linux操作系统的磁盘文件结构 linux操作系统中的文件操作 linux中的用户管理 网络配置管理 常用系统管理指令 linux ...

  4. Codeforces Round #390 (Div. 2)

    时隔一个月重返coding…… 期末复习了一个月也不亏 倒是都过了…… 就是计组61有点亏 复变68也太低了 其他都还好…… 假期做的第一场cf 三道题 还可以…… 最后room第三 standing ...

  5. 数据库索引的实现原理(笔记)详细http://www.linezing.com/blog/?p=798#nav-1

    数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询.更新数据库表中数据.索引的实现通常使用B树及其变种B+树. 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某 ...

  6. Android 6.0之权限管理

    安卓6.0的权限体系分为非敏感权限和敏感权限,非敏感权限默认获取,可以手动关闭. 敏感权限必须由app在运行时动态申请.而存储读写空间权限是一个敏感权限,不是一个“很正常的必须权限”. 安卓并不是想要 ...

  7. SAP HANA中创建层次分析视图(Hierarchy Analytic View)

    1. 创建层次Attribute View: ATTR_PRODUCT_HIERACHY ref:  http://www.cnblogs.com/omygod/archive/2013/04/30/ ...

  8. AJAX在Struts2中使用

    前台页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnc ...

  9. String 类上的常用操作

    java 中String 类上的常用操作: 首先创建对象  String line = new String("String demo"); String line2 = new ...

  10. TOMcat9 免安装版的配置

    在这里默认大家都安装了jdk并且配置了java的环境,网上教程很多. 在tomcat官网(http://tomcat.apache.org/download-90.cgi)上下载和自己系统匹配的安装包 ...