我们都知道两个指针指向同一个变量时如果一个指针被释放那么另一个就会出问题

为了说明问题我做了一个很恶心的小例子

class C
{
public :
C(int v)
{
ptrInt=new int;
*ptrInt=v; valueInt = v;
} ~C()
{ }
void DelIntV()
{
valueInt=;
delete ptrInt;
} C(const C& c)
{ }
int * ptrInt;
int valueInt;
private: }; int main()
{
C c1();
C c2();
c2=c1;
std::cout<<"ptrInt "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
c1.DelIntV(); std::cout<<"address "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
std::cin.get();
return ;
}

这是把c1赋值给了c2后把指针ptrInt的值输出和valueInt输出,再把c1的指针给delete,valueInt赋值为0

再输出c2的ptrInt和valueInt就会发现指针有问题,看一下输出结果:

已经不对了吧。

为了解决这样的问题我第一个想到的就是重载操作符=

C& operator=(const C &c)
{
if(this!=&c)
{
delete ptrInt;
ptrInt = new int;
*ptrInt= *c.ptrInt;
valueInt=c.valueInt;
}
return *this;
}

完整代码

class C
{
public :
C(int v)
{
ptrInt=new int;
*ptrInt=v; valueInt = v;
} ~C()
{ }
void DelIntV()
{
valueInt=;
delete ptrInt;
} C(const C& c)
{ }
int * ptrInt;
int valueInt; C& operator=(const C &c)
{
if(this!=&c)
{
delete ptrInt;
ptrInt = new int;
*ptrInt= *c.ptrInt;
valueInt=c.valueInt;
}
return *this;
}
private: }; int main()
{
C c1();
C c2();
c2=c1;
std::cout<<"ptrInt "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
c1.DelIntV(); std::cout<<"address "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
std::cin.get();
return ;
}

再看一下输出结果:

这下就正确了吧,但是如果 我们在main函数里做一个修改

int main()
{
C c1();
C c2=c1;//这里直接赋值
std::cout<<"ptrInt "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
c1.DelIntV(); std::cout<<"address "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
std::cin.get();
return ;
}

这样后错误就又和之前一样了,为什么呢,

编译器将在c类里找一个副本构造器(copy constructor)如果找不到它会自己创建一个,

即使我们对操作符=进行了重载也没有用,由编译器自己创建的副本构造器仍会以"逐们复制"

的方式把c1赋值给c2

这样我们还要重新实现这个副本构造器,

className(const className &cn);

我是这样做的

    C(const C& c)
{
*this=c;
}

这里的=其实就是调用的重载的=方法

完整代码

class C
{
public :
C(int v)
{
ptrInt=new int;
*ptrInt=v; valueInt = v;
} ~C()
{ }
void DelIntV()
{
valueInt=;
delete ptrInt;
} C(const C& c)
{
*this=c;
}
int * ptrInt;
int valueInt; C& operator=(const C &c)
{
if(this!=&c)
{
delete ptrInt;
ptrInt = new int;
*ptrInt= *c.ptrInt;
valueInt=c.valueInt;
}
return *this;
} private: }; int main()
{
C c1();
C c2=c1;//这里直接赋值
std::cout<<"ptrInt "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
c1.DelIntV(); std::cout<<"address "<<c2.ptrInt<<" value "<<*c2.ptrInt<<std::endl;
std::cout<<"valueInt "<<c2.valueInt<<std::endl;
std::cin.get();
return ;
}

结果

c++ 副本构造器的更多相关文章

  1. 小甲鱼C++笔记(下)25-48

    二十五  二十六  二十七  重载 运算符重载 1. 作为成员函数 #include <iostream> using namespace std; class Add { private ...

  2. java源码解析之String类(二)

    上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...

  3. js--使用构造器函数来新建对象及操作

    通过new操作符来调用函数,来达到访问对象this值得目的,构造器将其创建的对象返回给我们. 直接上代码 //创建构造器函数 function Gadget(name, color){ this.na ...

  4. JavaSE——面向对象与面向过程、类与对象、(属性、方法、构造器)等

    一:面向对象与面向过程 二者都是一种思想,面向对象是相对于面向过程而言的. 面向过程: 1.面向过程思想强调的是过程(动作). 2.在面向过程的开发中,其实就是面向着具体的每一个步骤和过程,把每一个步 ...

  5. 6、Java类、对象、构造器、引用类型内存基本知识、引用类型值传递

    1.面向对象三大特征: 封装:encapsulation 继承:inheritance 多态:polymorphism 2.类中 数据特征(property):属性(attribute)静态的stat ...

  6. 一文了解 Java 中的构造器

    摘要:Java 也采用了构造器,并且还提供了一个垃圾收集器(garbage collector),当不再使用内存资源的时候,垃圾收集器会自动将其释放. 本文分享自华为云社区<一文带你了解 Jav ...

  7. Kafka副本管理—— 为何去掉replica.lag.max.messages参数

    今天查看Kafka 0.10.0的官方文档,发现了这样一句话:Configuration parameter replica.lag.max.messages was removed. Partiti ...

  8. Java之类的构造器(反射)

    反射: Java反射机制:指的是在Java程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法.这种动态获取类的内容以及动态调用对象的 ...

  9. Swift3.0P1 语法指南——构造器

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...

随机推荐

  1. Zero to One读后感

    Zero to One是一本不错的书,无论你是在职场还是在创业都应该看看先.书中没有告诉你任何的职业技巧,但是很明确的告诉了你应该有的思考方式,告诉你人与机器的关系,告诉成功企业固有的模式以及你为什么 ...

  2. SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  3. python标准库00 学习准备

    Python标准库----走马观花 python有一套很有用的标准库.标准库会随着python解释器一起安装在你的电脑上的.它是python的一个组成部分.这些标准库是python为你准备的利器,可以 ...

  4. GNU C 内联汇编介绍

    GNU C 内联汇编介绍 简介 1.很早之前就听说 C 语言能够直接内嵌汇编指令.但是之前始终没有去详细了解过.最近由于某种需求,看到了相关的 C 语言代码.也就自然去简单的学习了一下如何在 C 代码 ...

  5. Linux 下从头再走 GTK+-3.0 (四)

    实际的应用中,往往有很多个控件, 同样GTK提供了很多种布局方案,Box, Fixed , Table , Grid 等. 接下来试试网格布局 Grid. 我们创建 example4.c ,内容如下: ...

  6. Python教程[廖雪峰],主要是实践

  7. 彻底解决mysql中文乱码的办法,修改mysql解压缩版(免安装版或zip版)字符编码

    MySQL会出现中文乱码的原因不外乎下列几点:1.server本身设定问题,例如server字符编码还停留在latin12.table的语系设定问题(包含character与collation)3.客 ...

  8. ural Cipher Message

    Cipher Message Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Desc ...

  9. java 关于多线程高并发方面

    转有关的文章链接: Java 高并发一:前言: http://www.jb51.net/article/92358.htm Java 高并发二:多线程基础详细介绍 http://www.jb51.ne ...

  10. https网站跳转到http网站时,referrer获取不到的问题

    工作中,有一个活动列表页A,要链接到具体的活动详情页B,A页面放在https网站上,B页面放在http网站上,从https跳转到http网站时,为了用户隐私安全信息,浏览器默认不传送referrer ...