c++ 入门之深入探讨拷贝函数和内存分配
在c++入门之深入探讨类的一些行为时,说明了拷贝函数即复制构造函数运用于如下场景:
- 对象作为函数的参数,以值传递的方式传给函数。
- 对象作为函数的返回值,以值的方式从函数返回
- 使用一个对象给另一个对象初始化
针对上述的三种情况,实际上很多时候,我们都会用到;如果我们采用系统默认的拷贝函数,程序容易发生我们无法掌控的错误。通常情况,我们会注意到:我们在定义一个拷贝函数的时候,往往会这么定义:classname(const classname& A),为什么一定要用引用类型传递参数呢?如果我们不采用引用类型,采用值传递:就陷入了问题的本身:我们试图定义自己的拷贝函数来解决值传递的过程中,调用拷贝函数的问题。假如我们的拷贝函数变量是值传递,那么当调用这个拷贝函数的时候,由于拷贝函数本身就是值传递,便使得再次调用拷贝函数,而一旦进行调用,又遇到值传递.....于是,陷入了死循环的过程。所以:拷贝函数一定要采用引用传递参数。
关于new和delete:用new生成的空间在堆区,而不是栈区。
我们关注一下这个事实:
class StringBad
{
private:
char *str;
int len;
static int num_strings; //= 0;//可见除了const 量之外,类内部成员是不能在内部赋初值的
public:
StringBad(const char * s);
StringBad();
~StringBad(); friend std::ostream & operator<<(std::ostream & os, const StringBad & st);
};
上面定义了一个类:关于这个类不再赘述类的一般特性。在此,我们仅仅关注这个点:char *str;即这个字符指针成员。如果我们定义了一个对象A,A.str = "hello world!".A.len = 10。假如,我们再定义一个对象B,B = A,那么,B.str = "hello world!",B.len = 10,这个也没什么问题。但问题在于:B.len 和A.len 变量的地址是不同的。B.str和A.str这两个指针自己的地址自然也是不同的,但他们却指向了同一个“"hello world!",也就是说,在定义B=A时,并没有将"hello world!"复制一遍,复制到另外一个内存空间,然后让B.str指向了这里。而是让B.str也指向了这个 "hello world!".即使得这个 "hello world!"看起来像一个公共资源!这实际上是十分危险的!!!假如我们变量B过期了,要被销毁,其指针变量指向的"hello world!"所在的内存被delete所回收,那么其实A.str这个时候指向的内存并不是“hello world”,而我们的本意是,让这些对象彼此独立,互不干扰,除非我们想这样(比如静态成员的存在)。
实际上,上述问题反映了一个重要的问题:深拷贝和浅拷贝。如果我们只是复制了地址,而没有赋值地址的内容,则是浅拷贝,否则为深拷贝。
总结:当我们在类中遇到指针成员时,务必要使得我们的拷贝函数成为深拷贝,而不是浅拷贝!!!(具体做法参考收藏的他人博文)
我们应该了解new ,delete 运作的本质:
char * p;
p = new char[];
上述描述了 p 首先是一个指针,然后通过new 开辟了10个char型空间,我们让p指向这个10个char型空间。
当对象被销毁时,会调用析构函数。析构函数中,应该包含:
delete[] p;
这表明了当这个对象被销毁后,与之关联的内存空间应该被销毁。delete[] p是什么含义呢?
delete并不是说我们销毁了p 这个变量,而是销毁了p指向的内存区。实际上P并不需要我们去销毁,因为p本身在栈区,而栈区的内存机制,我们是很清楚的。
我们再次强调:之所以我们要用delete来管理内存,是因为new分配的空间在堆区,堆区并不会随着对象的销毁而自行销毁,需要人为的对其销毁,new -delete就是“创建堆区空间”——“销毁堆区的机制”。但是作用域内的普通变量就不一样:他们生存在栈区,栈区的变量会随着作用域的变化,完成出栈,从而释放内存!
c++ 入门之深入探讨拷贝函数和内存分配的更多相关文章
- DLL函数中内存分配及释放的问题
DLL函数中内存分配及释放的问题 最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了.主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的 情况,这里总结一下,做为资料. 错误 ...
- C++ 虚函数的内存分配
1.无继承的普通类: 在有虚函数的情况下类会为其增加一个隐藏的成员,虚函数表指针,指向一个虚函数表,虚函数表里面就是类的各个虚函数的地址了.那么,虚函数表指针是以什么模型加入到类里面的,虚函数表里 ...
- 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
包.变量和函数 一.举个例子 现在我们来建立一个完整的程序main.go: // Golang程序入口的包名必须为 main package main // import "golang&q ...
- Python: 拷贝函数签名
使用场景有很多,比如C API在Python下很多都变成了(*args, **kwargs)的参数,这时候可能需要为其添加一个更严格签名来约束参数. 查了许多资料,能有效的拷贝函数签名貌似只能通过动态 ...
- 10-Python3从入门到实战—基础之函数
Python从入门到实战系列--目录 函数的定义 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数的语法 def 函数名(参数列表): 函数体 函数代码块以 def 关键词开头 ...
- c++不自动生成相关函数比如赋值、拷贝函数
默认情况下,如果没有明确声明某些函数比如赋值.拷贝函数,c++会自动生成这些函数,通常他们是对成员进行by-value拷贝,有些时候,赋值.拷贝对象并无什么意义或者不合理,比如对于socket或者th ...
- C++ 内存拷贝函数 memcpy
在C/C++中经常会遇到对一段固定的连续内存进行拷贝操作, 这时候我们就需要用到 <cstring> 头文件 中的 memcpy 函数. 具体使用如下: 其中 , ...
- c++中内存拷贝函数(C++ memcpy)详解
原型:void*memcpy(void*dest, const void*src,unsigned int count); 功能:由src所指内存区域复制count个字节到dest所指内存区域. 说明 ...
- C语言——常用标准输入输出函数 scanf(), printf(), gets(), puts(), getchar(), putchar(); 字符串拷贝函数 strcpy(), strncpy(), strchr(), strstr()函数用法特点
1 首先介绍几个常用到的转义符 (1) 换行符“\n”, ASCII值为10: (2) 回车符“\r”, ASCII值为13: (3) 水平制表符“\t”, ASCII值为 9 ...
随机推荐
- SQLServer2016 AlwaysOn AG基于工作组的搭建笔记
最近搭建了一套SQLServer2016 AlwaysOn AG. (后记:经实际测试,使用SQLServer2012 也同样可以在Winserver2016上搭建基于工作组的AlwaysOn AG, ...
- Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)
execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x8 ...
- C# -- 索引器、枚举类型
C# -- 索引器.枚举类型 索引器允许类或结构的实例就像数组一样进行索引. 无需显式指定类型或实例成员,即可设置或检索索引值. 索引器类似于属性,不同之处在于它们的访问器需要使用参数. 1. 索引器 ...
- Servlet(二):初识Servlet
在手动写完一个Servlet小例子后,是不是有很多疑问,接下来会为大家详细介绍Servlet的知识. 1.什么是Servlet 是在服务器上运行的小程序.一个servlet就是一个Java类,并且可以 ...
- Elixir 单元测试
概述 elixir 中自带了单元测试框架 ExUnit ,其中提供单元测试的一系列,主要包含以下模块: ExUnit: 单元测试框架 ExUnit.Assertions: 断言 ExUnit.Case ...
- Kernel数据结构移植(list和rbtree)
主要移植了内核中的 list,rbtree.使得这2个数据结构在用户态程序中也能使用. 同时用 cpputest 对移植后的代码进行了测试.(测试代码其实也是使用这2个数据结构的方法) 内核代码的如下 ...
- vue v-nav指令属性列表
v-nav指令属性列表 属性名 属性描述 类型 必选 默认 title 导航栏标题 String No 空字符串 showBackButton 是否显示(左边的)返回按钮 Boolean No fal ...
- mysql统计一年12月的数据
效果图: select end) as 一月份, end) as 二月份, end) as 三月份, end) as 四月份, end) as 五月份, end) as 六月份, end) as 七月 ...
- 「APIO2017」商旅
「APIO2017」商旅 题目描述 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所深深吸引,决定定居于此,做一个商人.科巴有 \(N\) 个集市, ...
- linux学习笔记整理(七)
第八章 Centos7软件包的管理与安装本节所讲内容:8.1 使用rpm命令-安装-查看-卸载-rpm软件包8.2 yum管理软件包8.3 实战tar源码包管理-srpm源码包安装方法 8.1 软件包 ...