C++_CopyConstructor(副本构造器 防止指针重复释放)
来源:互联网 发布:社交网络 百度云盘 编辑:程序博客网 时间:2024/06/07 13:50
1.背景说明:
我们可以将一个对象赋值给一个类型与之相同的变量,编译器将生成必要的代码将 源对象 各属性的值分别赋值给 目标对象 的各成员,这种赋值行为称之为“逐位复制(copy)”,在绝大多数场合下都没有问题,但是如果某些成员是指针的话,问题就来了:对象成员进行逐位复制的结果就是:你将拥有两个一模一样的实例,而这两个副本里的同名指针将指向相同的地址!于是,当删除其中一个对象时,它所包含的指针也将被删除,若此时另外一个副本对象还在引用这个指针就会出现内存问题,导致程序崩溃。(“同时”删除两个对象,也是无效的,因为CPU是逐条指令执行的,总会有先后顺序)
2.解决方法一: 重载等号(=)操作符,新的指针使用新的的内存地址,原来的指针内存地址不变,并使用下列赋值:
Myclass obj1;
Myclass obj2;
obj1=obj2;
风险:若在创建obj2实例对象时直接初始化(Myclass obj2=obj1)则实际上编译器在编译时并不使用自定义的重载等号(=)操作符,而是去寻找副本构造器,若没有就会自行创建一个,依然会进行“逐位复制(copy)”,造成指针对象指向同一内存块!所以有了解决方法二:不让编译器自定义副本构造器,而是自定义一个副本构造器。
3.解决方法二:自定义副本构造器,在其中使用 重载等号(=)操作符
4.代码 as follows:
// CopyConstructor.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>class MyClass{public:MyClass(int *P);//主构造器 传入整型指针MyClass(const MyClass &rhs);//重载构造函数 副本构造器~MyClass();MyClass &operator=(const MyClass &rhs);//重载赋值操作符 返回类型依然是MyClassvoid print();private:int *ptr; //私有成员变量 指针类型 //验证:赋值操作时 两对象的指针类型成员 同时指向同一块地址,释放时 造成重复释放内存错误 //所以有了副本构造器,两对象赋值时,对指针成员 规划两块内存地址,存放同一个数值,地址释放时互不影响};//MyClass 成员定义MyClass::MyClass(int *p){std::cout << "Into MainConstructor\n";ptr = p;std::cout << "Leave MainConstructor\n";}MyClass::MyClass(const MyClass &rhs) {std::cout << "Into CopyConstructor\n";*this = rhs;//为方便使用这样的操作如 MyClass obj2=obj1;//定义时直接构造std::cout << "Leave CopyConstructor\n";}MyClass::~MyClass(){std::cout << "Into Destructor\n";delete ptr;//释放指针指向的内存块(指针还存在,但不指向任何内存)std::cout << "Leave Destructor\n";}MyClass & MyClass::operator=(const MyClass & rhs){std::cout << "Into Assignment OperatorOverloading\n"; //赋值操作符重载if (this != &rhs)//如 obj2=obj1;{delete ptr; //删除新对象obj2.ptr指针成员 在定义时指向的地址ptr = new int; //为新对象obj2.ptr指针成员 分配新的内存地址(即指向新的内存地址)*ptr = *rhs.ptr; //将原对象obj1.ptr指针指向的内容 存入新对象obj2.ptr新分配的地址中去 //结果:新对象obj2.ptr拥有了新地址;原obj1.ptr地址不变 }else {std::cout << "The Same Object on both sides of \"=\" , No action!\n"; // obj1 = obj1;}std::cout << "Leave Assignment OperatorOverloading\n"; return *this;}void MyClass::print(){std::cout << *ptr << std::endl;}int main(){MyClass obj1(new int(1));//初始化obj1对象MyClass obj2(new int(2));obj2 = obj1;obj1.print();obj2.print();std::cout << "--------------------------------------------------\n";MyClass obj3(new int(3));MyClass obj4 = obj3; //obj4定义 并初始化obj3.print();obj4.print();std::cout << "--------------------------------------------------\n";MyClass obj5(new int(5));obj5 = obj5;obj5.print();system("pause"); return 0;}
0 0
- C++_CopyConstructor(副本构造器 防止指针重复释放)
- 指针重复释放
- 【009】副本构造器
- c++ 副本构造器
- 副本构造器
- c++ 副本构造器
- 副本构造器
- C++ 副本构造器
- 指针的传递并不是构造副本
- 拷贝构造函数--内存被重复释放的隐形人
- Study C#《构造器中代码重复问题》
- C中防止重复定义时要加下划线
- 20、C语言防止重复编译
- 【C++】 防止重复包含头文件
- C指针(一) - 申请和释放内存
- C指针(一) - 申请和释放内存
- 指针空间的申请和释放(C)
- C语言指针开辟内存释放内存
- Exchanger的使用
- 随性
- 数据结构-高级排序
- 【NDN安全】Poseidon: Mitigating Interest Flooding DDoS Attacks in Named Data Networking 学习笔记
- jQuery插件slides实现无缝轮播图特效
- C++_CopyConstructor(副本构造器 防止指针重复释放)
- 非计算机专业,如何学习计算机视觉?
- 寻找丑数
- 九度OJ-题目1173:查找-10网研上机A
- 《第一行代码》Android 学习笔记
- [BFS]poj 2251 Dungeon Master
- 基于UDP的select函数用法
- (LeetCode) 268. Missing Number
- 九度OJ-题目1174:查找第K小数-10网研上机B