C++构造与析构
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++构造与析构的更多相关文章
- C++浅析——继承类中构造和析构顺序
先看测试代码,CTEST 继承自CBase,并包含一个CMember成员对象: static int nIndex = 1; class CMember { public: CMember() { p ...
- Effective C++ -----条款09:绝不在构造和析构过程中调用virtual函数
在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).
- 【09】绝不在构造和析构过程中调用virtual方法
1.绝不在构造和析构过程中调用virtual方法,为啥? 原因很简单,对于前者,这种情况下,子类专有成分还没有构造,对于后者,子类专有成分已经销毁,因此调用的并不是子类重写的方法,这不是程序员所期望的 ...
- C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)
这是我的感觉,具体需要研究一下- 找到一篇文章:在构造和析构中抛出异常 测试验证在类构造和析构中抛出异常, 是否会调用该类析构. 如果在一个类成员函数中抛异常, 可以进入该类的析构函数. /// @f ...
- STL——空间配置器(构造和析构基本工具)
以STL的运用角度而言,空间配置器是最不需要介绍的东西,它总是隐藏在一切组件(更具体地说是指容器,container)的背后,默默工作,默默付出.但若以STL的实现角度而言,第一个需要介绍的就是空间配 ...
- 魔法方法:构造和析构 - 零基础入门学习Python041
魔法方法:构造和析构 让编程改变世界 Change the world by program 构造和析构 什么是魔法方法呢?我们来系统总结下: - 魔法方法总是被双下划线包围,例如__init__ - ...
- 再探Delphi2010 Class的构造和析构顺序
发了上一篇博客.盒子上有朋友认为Class的构造和析构延迟加载.是在Unit的初始化后调用的Class的构造.在Unit的反初始化前调用的Class的析构函数. 为了证明一下我又做了个试验 unit ...
- Effective C++_笔记_条款09_绝不在构造和析构过程中调用virtual函数
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为方便采用书上的例子,先提出问题,在说解决方案. 1 问题 1: ...
- STL—对象的构造与析构
STL内存空间的配置/释放与对象内容的构造/析构,是分开进行的. 对象的构造.析构 对象的构造由construct函数完成,该函数内部调用定位new运算符,在指定的内存位置构造对象 ...
- C++反汇编第二讲,不同作用域下的构造和析构的识别
C++反汇编第二讲,不同作用域下的构造和析构的识别 目录大纲: 1.全局(静态)对象的识别,(全局静态全局一样的,都是编译期间检查,所以当做全局对象看即可.) 1.1 探究本质,理解构造和析构的生成, ...
随机推荐
- samba 开启
1.查询samba服务安装好没 2.安装samba服务 3.增加以下几个条目 4.useradd smbuser 5.在重启中注意的问题 5.详细请查看 http://jingyan.baidu.co ...
- Cracking the Coding Interview 第二章
2.2 链表中倒数第k个结点 输入一个链表,输出该链表中倒数第k个结点. 思路:快慢指针(error: 判断是否有可行解,否则返回null, while, if 后加空格) /* public cla ...
- ECMAScript6之String类型的扩展
String类型的扩展 模板字符串 模板字符串是字符串的增强版,既可以当做普通的字符串使用,也可以在字符串中嵌入变量,它用反引号`来表示. //普通字符串 `In javascript '\n' is ...
- python3 流程控制
表达式if ... else >>> if 3 > 4: ... print('False') ... else: ... print('True') ... True 表达式 ...
- js判断数组里面的值是否相等。
var zhi=[]; var zhiT=[]; //var arr=["a","b","a","a"]; var ar ...
- zabbix 布署实践【5 使用邮箱SMTP SSL推送告警邮件】
由于传统的邮件推送脚本使用smtp 25端口,在各大邮箱提供商已不适用,已经向SSL过渡,这里以QQ邮箱为例,使用SSL 465端口 登录zabbix-server 进入 cd /usr/lib/za ...
- hdu1028
#include<stdio.h>#include<string.h>const int MAXN=130;int dp[MAXN][MAXN];//dp[i][j]表示 i ...
- insertable = false, updatable = false的使用
转自:insertable = false, updatable = false的使用 当使用JPA配置实体时,如果有两个属性(一个是一般属性,一个是多对一的属性)映射到数据库的同一列,就会报错. 这 ...
- Python学习笔记——基础篇【第五周】——算法(4*4的2维数组和冒泡排序)、时间复杂度
目录 1.算法基础 2.冒泡排序 3.时间复杂度 (1)时间频度 (2)时间复杂度 4.指数时间 5.常数时间 6.对数时间 7.线性时间 1.算法基础 要求:生成一个4*4的2维数组并将其顺时针旋 ...
- [Q]复制授权了文件但仍显示“未注册”问题(安装在非默认目录或目录包含中文)
1. 注意要将解压后的文件复制到CAD批量打图精灵安装目录,而不要复制文件夹,复制是提示是否需要覆盖,要选择覆盖. 2. 若通过第1步操作仍然显示“未注册”,则可能是由于安装目录含有中文或者不是默认目 ...