博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++中的new和delete在类中的应用
阅读量:4223 次
发布时间:2019-05-26

本文共 2317 字,大约阅读时间需要 7 分钟。

类的构造函数和析构函数的一个典型应用就是:在构造函数中用new为指针成员开辟独立的动态内存空间,而在析构函数中用delete来释放它们。

一个类的成员的数据类型可以是任何有效的合法类型,当数据类型为指针时,这样的成员称为指针成员,注意有潜在的危险性。

class CName

{

public:

CName()    // A:显式默认构造函数

{

strName = NULL;

}

CName(char *str)  // B: 

strName = str;

}

~CName()  { }   //显式默认析构函数

char *getName()

{

return strName;

}

private:

char *strName;

};

int main()

{

char *p = new char[5]; // 为p开辟内存空间

strcpy(p, "DONG"); // p指向的内存空间值为 "DONG"

CName one(p); // 对象初始化

delete []p; // 释放P的内存空间

cout<<one.getName()<<endl;

return 0;

}

以上代码会出现问题,由于 ” CName one(p) “,调用的是B重载构造函数,从而使得私有指针成员 strName指向等于p的指向,而p指向的是new开辟的内存空间,其内容是”DONG“,一旦p指向的内存空间删除,p的指向就不确定了,此时,strName指向也不确定。

为了保证类的封装性,类中的指针成员指向的内存空间必须在类中自行独立开辟和释放。

改进后的代码:

class CName

{
public:
CName()    // A:显式默认构造函数
{
strName = NULL;
}
CName(char *str)  // B: 
//strName = str;
//在类的内部自行开辟内存空间
strName = (char *)new char[strlen(str)+1];
strcpy(strName,str);
}
~CName()  
{
if (strName)
{
delete []strName;
strName = NULL;
}
}   //显式默认析构函数
char *getName()
{
return strName;
}
private:
char *strName;
};
int main()
{
char *p = new char[5]; // 为p开辟内存空间
strcpy(p, "DONG"); // p指向的内存空间值为 "DONG"
CName one(p); // 对象初始化
delete []p; // 释放P的内存空间
cout<<one.getName()<<endl;
return 0;
}

对象赋值和拷贝

class CName;

CName o1("DONG"); // A:通过构造函数设定初值

CName o2(o1); //B:通过指定对象设定初值

B语句通过将o1作为o2的初值,o2的初始化形式要调用相应的构造函数,事实上,CName隐含一个特殊的默认构造函数,其原型为:CName (const CName &);这种特殊的默认构造函数称为:默认拷贝构造函数。在C++中,每个类总有一个默认拷贝构造函数,目的是保证B语句中对象初始化形式的合法化,功能等价于:CName o2=o1;

没有指针成员时的情况是:

class CData

{

public:

CData( int data=0 )

{

m_nData = data;

}

~CData()  {

}

int getData()

{

return m_nData;

}

private:

int  m_nData;  //非指针型成员变量

};

下面的对象初始化形式是合法的

CData c1(3); // 通过重载构造函数设定初值

CData c2(c1); // 通过默认拷贝构造函数设定初值

//等价于 CData c2=c1;

同类型的变量可以直接用 ” = “ 来赋值,对于CData c2=c1; C++中赋值运算符的操作就是:将右操作对象的内容拷贝到左操作对象的内存空间中去。

有无 指针成员的区别在哪里?

CName的数据成员strName是一个” char * “指针,其自身内存空间存放的是指针的地址,因而其数据的存储还需另外开辟一个不依附于外部的独立的内存空间,由于m_nData自身的内存空间就是用来存储数据的,因此CData对象初始化所进行的数值拷贝是有效的。

浅拷贝

定义:每一个C++类都有一个隐式的默认拷贝构造函数,目的是保证类对象拷贝初始化方式的合法性,其功能是将一个已定义的对象所在的内存空间的内容依次拷贝到被初始化的对象的内存空间中去,这种内存空间内容的拷贝方式称为--浅拷贝。

深拷贝

定义:对于数据成员有指针类型的类来说,都会出现上述CName的问题,由于默认拷贝构造函数无法解决,必须自己定义一个拷贝构造函数,在数值拷贝之前,需要为指针类型的数据成员另辟一个独立的内存空间,因而称为--深拷贝

对于类CName的拷贝构造函数,可以有的合法声明方式有:

CName (CName &x);

CName (const CName &x);

CName (CName &x, ...);

CName (const CName &x, ...);

一旦类中定义了拷贝构造函数,隐式的默认拷贝构造函数和隐式的默认构造函数就失效了!因为拷贝构造函数也是构造函数一种。

转载地址:http://nazqi.baihongyu.com/

你可能感兴趣的文章
独家 | 一文读懂人工神经网络学习原理
查看>>
机器学习在热门微博推荐中的应用
查看>>
数据蒋堂 | 文件的性能分析
查看>>
国家、数据、治理:排列组合文字游戏下的思考(附PPT下载)
查看>>
一文读懂生成对抗网络GANs(附学习资源)
查看>>
值得收藏的45个Python优质资源(附链接)
查看>>
2017年度NLP领域论文TOP10(附链接)
查看>>
精选NLP、CV领域论文TOP10(附链接)
查看>>
数据蒋堂 | DB与NoSQL的访问性能
查看>>
教你简单解决过拟合问题(附公式)
查看>>
非单身勿点,这里是单身汪专属情人节~
查看>>
2018新年快乐 !(附幸运读者名单)
查看>>
大年初一,今年的春晚你看了吗?
查看>>
大年初二,今年过年你选择在男方家过还是女方家过?
查看>>
大年初三,过年期间最让你受不了的习俗有哪些?
查看>>
大年初四,你认为在南方过年和在北方过年最大的不同是什么?
查看>>
大年初五,Python、Go、C...你最爱用哪种语言?
查看>>
大年初六,你最崇拜的数据科学大咖是谁?
查看>>
大年初七,发paper、学Python...分享一下你的学习计划吧~
查看>>
数据蒋堂 | 报表开发的现状
查看>>