C++深入理解(7)------类和动态分配内存(读书笔记)

    在类内给成员变量分配内存使用new和delete中最常遇到的问题就是内存泄漏,造成这样的原因往往是不对应,而且对C++的构造函数和析构函数不是很了解。C++会默认提供下面的函数:

    • 默认构造函数,如果没有定义构造函数:
    • 默认析构函数,如果没有定义;
    • 复制构造函数,如果没有定义;
    • 赋值运算符,如果没有定义:
    • 地址运算符,如果没有定义。

    如果没有构造函数就会存在提供默认构造函数,如果定义了,就不会提供,但是复制构造函数是默认隐藏提供的,而且赋值运算符,即将一个类对象赋值给同类的另一个对象。这里分别讲解需要注意的要点。

1、复制构造函数:复制构造函数用于将一个对象复制到另一个对象,其原型为: Classname (const Classname &);

    需要知道何时被使用,其使用的地方大致集中在3处:在用一个对象给另一个对像用=初始化时;在传入实参的时候会默认复制一个副本,调用复制构造函数;在函数返回值的时候也会返回副本,即调用一个复制构造函数。第二第三个都比较好理解,着重说一下第一个,因为涉及到好多的初始化方式:

StringBad ditto (motto) ;         // calls StringBad (const StringBad A)
StringB admetoo = motto;          // calls StringBad (const StringBad &)
StringBad also = StringBad(motto); // calls StringBad (const StringBad &)
StringBad * pStringBad = new StringBad (motto);

    以其中的第二条作为例子,说下过程,这里首先调用admetoo的复制构造函数,并把motto作为参数穿进去,将motto的所有成员变量的值都传给admetoo的成员变量,这样看上去两者就有相同的值了。

    隐式的构造函数会带来很多不便,隐式的复制构造函数会将原对象的属性值原封不动的复制给新对象,这样在复制指针的时候实际上覆制的为同一个指针,当操作被复制的新对象的指针后,原来对象的指针也会受到影响。所以在一个类中含有指针,或者含有静态变量,或者在构造函数中使用new的一般都要显示的重新定义复制构造函数(此过程被叫做深度复制)。

2、默认的赋值运算符:Class_name & Class_name::operator=(const Class_name &) ;

    虽然与复制构造函数稍有差别,但是在使用=的时候,实际是将原对象的数据赋值给新对象,新对象的指针等数据依然是原对象的值,会导致指针的不恰当操作。

//这种方式是:用有参数的和没参数的构造函数分别定义两个对象,然后让对象1给对象2赋值
StringBad headlinel("CeleryS talks at Midnight");
StringBad knot;
knot = headlinel;    // assignment operator invoked

     其最标准的写法如下:

StringBad & StringBad::operator = (const StringBad & st)
{
if (this == &st)   //object assigned to itself
return *this;     // all done
delete [] str;     // free old string
len = st.len;
str = new char [len + 1 ]; // get space for new string
std :: strcpy(str, st.str ); // copy the string
return *this ;         // return reference to invoking
}

    其实说到底就是在重载=,当然还可以传入不同的参数来重载出不同的运算符,如传入char*,就可以将char*赋值给stringbad。

3.包含类成员的类的逐成员赋值:

    如果类包含多个类,但是这些类都需要new属性,那么还需要在为这个大类重写复制构造函数吗?答案是不用的,这个类是有一定的智能型的,根据组件类的复制构造函数去逐个赋值。

        总结来说,当构造函数中包含new等动态分配内存的操作时,就要对赋值构造函数,赋值运算符等进行显示的定义,从而进行深度复制,防止使用默认的构造函数,使指针操作异常。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章