请教小弟我这个程序中那里发生了内存泄漏
请问我这个程序中那里发生了内存泄漏?
这是我的.h文件
.cpp文件
不注释掉243~245行代码,不会发生内存泄漏
不注释,调试状态下运行会出现
Detected memory leaks!
Dumping objects ->
{224} normal block at 0x00BA9CF8, 8 bytes long.
Data: < > CD CD CD CD CD CD CD CD
Object dump complete.
------解决思路----------------------
赋值操作的运算符重载中(CDArray & CDArray::operator = (const CDArray& b) ),没有把原先 m_pData所指的空间给释放掉。当为CDArray 对象赋一个新的对象的时候,会有内存泄露。
------解决思路----------------------
复制拷贝的时候,没有释放之前的内存。
------解决思路----------------------
问题在这
CDArray & CDArray::operator = (const CDArray& b) {
m_nSize = b.m_nSize;
m_capacity = b.m_capacity;
if(m_nSize){
m_pData = new double[m_capacity];
for(int i = 0 ; i<m_nSize; i++){
m_pData[i] = b.m_pData[i];
}
}
return *this;
}
你在实例化对象时,已经调用Init为m_pData开辟空间了,为何重载赋值还要开辟空间,那以前的空间不就成了孤魂野鬼了
这是我的.h文件
class CDArray
{
private:
double *m_pData; // 存放数组的动态内存指针
int m_nSize; // 数组的元素个数
int m_capacity; //数组容量
private:
void Init(); // 初始化
void Free(); // 释放动态内存
inline int InvalidateIndex(int nIndex) const ; // 判断下标的合法性
public:
CDArray(); // 缺省构造函数
CDArray(int nSize, double dValue = 0); // 其他构造函数,设置一定数组大小,并设置所有元素为0;当然还可以定义其他不同参数的构造函数,以方便用户使用
CDArray(const CDArray& arr); // 拷贝构造函数(最好为所有包含动态分配成员的类都提供拷贝构造函数)
~CDArray(); // 析构函数
void Print(); // 输出显示所有数组元素的值
int GetSize() ; // 获取数组大小(元素个数)
// int SetSize(int nSize); // 重新设置数组的大小。注:若nSize小于原数组大小,可截断取前nSize个元素作为新数组的元素;若nSize大于原数组大小,新增的元素的值设置缺省值0即可
double GetAt(int nIndex) const; // 获取某个元素
double operator[] (int nIndex) const ; // 重载[]操作符,以便像传统数组那样通过a[k]来获取元素值
int SetAt(int nIndex, double dValue); // 设置某个元素的值
int Pushback(double dValue); // 追加一个新的元素到数组末尾
int DeleteAt(int nIndex); // 从数组中删除一个元素
int InsertAt(int nIndex, double dValue); // 插入一个新的元素到数组中
CDArray &CDArray::operator = (const CDArray& array); // 重载赋值操作符号"="
};
.cpp文件
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
#include<windows.h>
#include "CDArray.h"
using namespace std;
//初始化,为每个变量申请空间
void CDArray::Init(){
m_nSize = 0;
m_capacity = 1;
m_pData = new double[m_capacity];
}
//释放动态空间
void CDArray::Free(){
delete []m_pData;
}
//检验下标是否在范围之内
int CDArray::InvalidateIndex(int Index) const{
if (Index <= m_nSize && Index >= 0)
return true;
else
return false;
}
//缺省构造函数
CDArray::CDArray(){
Init();
}
//构造函数
CDArray::CDArray(int nSize, double dValue){
m_nSize = nSize;
m_capacity = nSize;
m_pData = new double[nSize];
if (m_pData == NULL) {
cout << "分配空间失败";
}
for (int i = 0; i < m_nSize; i++)
{
m_pData[i] = dValue;
}
}
//拷贝构造函数 ,实现对对象的复制
CDArray::CDArray(const CDArray& arr){
*this = arr;
}
CDArray & CDArray::operator = (const CDArray& b) {
m_nSize = b.m_nSize;
m_capacity = b.m_capacity;
if(m_nSize){
m_pData = new double[m_capacity];
for(int i = 0 ; i<m_nSize; i++){
m_pData[i] = b.m_pData[i];
}
}
return *this;
}
//析构函数,释放动态空间
CDArray::~CDArray(){
Free();
}
//打印数组中的元素
void CDArray::Print(){
for (int i = 0; i < m_nSize; i++)
{
cout<< m_pData[i]<<'\t' ;
}
cout << '\n';
}
//获得数组中元素的个数
int CDArray::GetSize(){
return m_nSize;
}
//获取下标为Index的元素
double CDArray::GetAt(int Index) const{
if (InvalidateIndex(Index))
{
return *(m_pData + Index);
}
else
{
cout << "Index不合法请输入正确下标";
return -1;
}
}
//设置下标为Index的元素
int CDArray::SetAt(int nIndex, double dValue){
if (InvalidateIndex(nIndex))
{
*(m_pData + nIndex) = dValue ;
return 1;
}
else
{
cout << "Index不合法请输入正确下标";
return -1;
}
}
//向数组最后压入元素
int CDArray::Pushback(double dValue){
if ((m_nSize + 1) <= m_capacity){
//数组容量够用
SetAt(m_nSize, dValue); //压入数据
m_nSize++;
}
else{
double *temp;
//数组容量不够用,申请空间
temp = m_pData;
m_pData = new double[m_capacity * 2]; //数组容量翻倍
if (m_pData == NULL) {
cout << "分配空间失败";
return 1;
}
//copy数组
for (int i = 0; i < m_nSize; i++)
{
m_pData[i] = temp[i];
}
SetAt(m_nSize,dValue); //压入数据
m_capacity = m_capacity * 2; //容量翻倍
m_nSize ++; //元素个数加1
delete[] temp;
}
return 0;
}
//向数组中插入数据
int CDArray::InsertAt(int nIndex, double dValue){
if (InvalidateIndex(nIndex)){
double *temp = m_pData;
if ((m_nSize + 1) <= m_capacity){
//数组容量足够大
//后半段向后挪
for (int i = m_nSize; i > nIndex; i--)
{
m_pData[i] = temp[i-1];
}
SetAt(nIndex, dValue); //插入数据
m_nSize++; //元素个数加1
}
else{
//数组容量不够用,申请空间
m_pData = new double[m_capacity * 2]; //数组容量翻倍
if (m_pData == NULL) {
cout << "分配空间失败";
return 1;
}
//放入前半段
for (int i = 0; i < nIndex; i++)
{
m_pData[i] = temp[i];
}
//放入后半段
for (int i = nIndex; i < m_nSize; i++)
{
m_pData[i + 1] = temp[i];
}
SetAt(nIndex, dValue); //中间插入数据
m_capacity = m_capacity * 2; //容量翻倍
m_nSize++; //元素个数加1
delete[] temp;
}
temp = NULL;
return 0;
}
else{
cout << "请输入正确下标";
return -1;
}
}
//删除数组中数据
int CDArray::DeleteAt(int nIndex){
if (InvalidateIndex(nIndex)){
double *temp = m_pData;
if ((m_nSize-1) >= m_capacity / 2){
//删除后,数组元素超过容量的1/2,空间大小不变
//后半段向前挪
for (int i = nIndex; i < m_nSize - 1; i++)
{
m_pData[i] = temp[i + 1];
}
m_nSize--; //元素个数-1
}
else{
//删除后,数组元素不超过容量的1/2,空间大小减少一半
m_pData = new double[m_capacity / 2]; //数组容量减半
if (m_pData == NULL) {
cout << "分配空间失败";
return 1;
}
//放入前半段
for (int i = 0; i < nIndex; i++)
{
m_pData[i] = temp[i];
}
//放入后半段
for (int i = nIndex; i < m_nSize - 1; i++)
{
m_pData[i] = temp[i + 1];
}
m_nSize--; //元素个数-1
m_capacity = m_capacity / 2;
delete[] temp;
}
temp = NULL;
return 0;
}
else
{
cout << "请输入正确下标";
return -1;
}
}
double CDArray::operator[] (int nIndex) const {
return GetAt(nIndex);
}
void useClass(){
CDArray a;
a.InsertAt(0, 2.1);
a.Print();
a.Pushback(3.0);
a.Pushback(3.1);
a.Pushback(3.2);
a.Print();
a.DeleteAt(0);
a.Print();
a.InsertAt(0, 4.1);
a.Print();
CDArray acopy = a; //此处用到了拷贝构造函数
acopy.Print();
CDArray acopy2(a); //该语句等同于上面的语句,都是初始化
acopy2.Print();
//CDArray acopy3;
//acopy3 = a; //此处用到了赋值操作符号"="的重载
//acopy3.Print();
CDArray b;
b.Pushback(21);
b.Print();
b.DeleteAt(0);
b.Print();
b.Pushback(22);
//b.SetSize(5);
b.Print();
CDArray c;
c.Pushback('a');
c.Pushback('b');
c.Pushback('c');
c.InsertAt(0, 'd');
c.Print();
}
int main() {
useClass();
if (_CrtDumpMemoryLeaks()){
MessageBox(NULL, TEXT("memory leak detected!"), TEXT("warning"), MB_ICONINFORMATION | MB_YESNO);
}
}
不注释掉243~245行代码,不会发生内存泄漏
不注释,调试状态下运行会出现
Detected memory leaks!
Dumping objects ->
{224} normal block at 0x00BA9CF8, 8 bytes long.
Data: < > CD CD CD CD CD CD CD CD
Object dump complete.
------解决思路----------------------
赋值操作的运算符重载中(CDArray & CDArray::operator = (const CDArray& b) ),没有把原先 m_pData所指的空间给释放掉。当为CDArray 对象赋一个新的对象的时候,会有内存泄露。
------解决思路----------------------
复制拷贝的时候,没有释放之前的内存。
CDArray & CDArray::operator = (const CDArray& b) {
m_nSize = b.m_nSize;
m_capacity = b.m_capacity;
if(m_nSize){
m_pData = new double[m_capacity]; /m_pData leaks
for(int i = 0 ; i<m_nSize; i++){
m_pData[i] = b.m_pData[i];
}
}
return *this;
}
------解决思路----------------------
问题在这
CDArray & CDArray::operator = (const CDArray& b) {
m_nSize = b.m_nSize;
m_capacity = b.m_capacity;
if(m_nSize){
m_pData = new double[m_capacity];
for(int i = 0 ; i<m_nSize; i++){
m_pData[i] = b.m_pData[i];
}
}
return *this;
}
你在实例化对象时,已经调用Init为m_pData开辟空间了,为何重载赋值还要开辟空间,那以前的空间不就成了孤魂野鬼了