在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++ 入门之深入探讨拷贝函数和内存分配的更多相关文章

  1. DLL函数中内存分配及释放的问题

    DLL函数中内存分配及释放的问题 最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了.主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的 情况,这里总结一下,做为资料. 错误 ...

  2. C++ 虚函数的内存分配

    1.无继承的普通类:   在有虚函数的情况下类会为其增加一个隐藏的成员,虚函数表指针,指向一个虚函数表,虚函数表里面就是类的各个虚函数的地址了.那么,虚函数表指针是以什么模型加入到类里面的,虚函数表里 ...

  3. 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数

    包.变量和函数 一.举个例子 现在我们来建立一个完整的程序main.go: // Golang程序入口的包名必须为 main package main // import "golang&q ...

  4. Python: 拷贝函数签名

    使用场景有很多,比如C API在Python下很多都变成了(*args, **kwargs)的参数,这时候可能需要为其添加一个更严格签名来约束参数. 查了许多资料,能有效的拷贝函数签名貌似只能通过动态 ...

  5. 10-Python3从入门到实战—基础之函数

    Python从入门到实战系列--目录 函数的定义 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数的语法 def 函数名(参数列表): 函数体 函数代码块以 def 关键词开头 ...

  6. c++不自动生成相关函数比如赋值、拷贝函数

    默认情况下,如果没有明确声明某些函数比如赋值.拷贝函数,c++会自动生成这些函数,通常他们是对成员进行by-value拷贝,有些时候,赋值.拷贝对象并无什么意义或者不合理,比如对于socket或者th ...

  7. C++ 内存拷贝函数 memcpy

    在C/C++中经常会遇到对一段固定的连续内存进行拷贝操作,   这时候我们就需要用到   <cstring>  头文件  中的  memcpy  函数. 具体使用如下: 其中   ,   ...

  8. c++中内存拷贝函数(C++ memcpy)详解

    原型:void*memcpy(void*dest, const void*src,unsigned int count); 功能:由src所指内存区域复制count个字节到dest所指内存区域. 说明 ...

  9. C语言——常用标准输入输出函数 scanf(), printf(), gets(), puts(), getchar(), putchar(); 字符串拷贝函数 strcpy(), strncpy(), strchr(), strstr()函数用法特点

    1 首先介绍几个常用到的转义符 (1)     换行符“\n”, ASCII值为10: (2)     回车符“\r”, ASCII值为13: (3)     水平制表符“\t”, ASCII值为 9 ...

随机推荐

  1. IO Redirect 与 Pipe

    对于任何一个进程,在启动时,都会打开三个流:stdin(标准输入), stdout(标准输出), stderr(标准错误输出).Stdout,stderr是process与Display之间,stdi ...

  2. JavaScript -- 时光流逝(五):js中的 Date 对象的方法

    JavaScript -- 知识点回顾篇(五):js中的 Date 对象的方法 Date 对象: 用于处理日期和时间. 1. Date对象的方法 <script type="text/ ...

  3. Ubuntu16.04系统安装搜狗输入法详细教程(转载)

    1.下载搜狗输入法的安装包 下载地址为:http://pinyin.sogou.com/linux/ ,如下图,要选择与自己系统位数一致的安装包,我的系统是64位,所以我下载64位的安装包 2.按键C ...

  4. Linux 小知识翻译 - 「邮件服务器」

    这次聊聊「邮件服务器」. 邮件服务器上通常会运行2个服务端软件,「SMTP服务器」和「POP服务器或者IMAP服务器」. 这2个东西,也许使用邮件客户端的人立马就明白了.因为设置邮件客户端的时候,需要 ...

  5. ​June 10. 2018, Week 24th, Sunday

    There is no friend as loyal as a book. 好书如挚友,情谊永不渝. From Ernest Miller Hemingway. Books are my frien ...

  6. JAVA 容易忽略的东西

    Java中的取余会出现负数.用Math.floorMod()方法可以掰正,但是也仅限被除数是负数的情况,如果除数是负数,这个没用. 和C不一样,Java中的字符串是不可变字符串,不能修改Java字符串 ...

  7. Spring的通知类型,切入表达式写法

    转载自  https://www.cnblogs.com/ltfxy/p/9882697.html Spring中通知类型: 前置通知:目标方法执行之前进行操作,可以获得切入点信息 后置通知: 目标方 ...

  8. js证书批量生成与打包下载

    前边有提到最近的一个证书生成保存下载打印的需求. 之前实现的是一个单个操作的页面,现在把实现的批量效果和进度效果的代码展示出来. html <button class="btn btn ...

  9. 【BZOJ4298】[ONTAK2015]Bajtocja

    [BZOJ4298][ONTAK2015]Bajtocja Description 给定d张无向图,每张图都有n个点.一开始,在任何一张图中都没有任何边.接下来有m次操作,每次操作会给出a,b,k,意 ...

  10. python六十八课——网络编程之UDP协议

    1.1 概述 UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接.简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到 ...