0
点赞
收藏
分享

微信扫一扫

Docker容器tomcat中文名文件404错误不一定是URIEncoding,有可能是LANG=zh_CN.UTF-8引起

沐之轻语 42分钟前 阅读 0

类的动态内存分配和释放

C++能够在程序运行时决定内存的分配,而不是只在编译阶段,因此,就可以根据程序的需要,而不是根据一系列严格的存储类型规则来使用内存,C++使用new和delete运算符来动态控制内存,但是,在类中使用这些运算符会导致许多新的问题,在这种情况下,析构函数就是必不可少的,下面我们通过一个小程序来看一看这些问题,这个程序是在类中使用new和delete来存储释放字符串

我们将函数声明写在一个头文件,即stringbad.h

在头文件里定义了一个类,名为Stringbad

在类函数定义文件中,即stringbad.cpp

我们在主函数文件main.cpp中,测试函数传递类的引用以及类的值 

特殊成员函数

复制构造函数

我们上面所说的问题其实就是由特殊的成员函数引起的,这些成员函数都是编译器进行自动定义的,就Stringbad而言,这些函数的行为与我们类的设计不符,C++会自动提供下列的成员函数

更准确的说,如果程序使用对象的方式要求我们这样做,编译器就是生成上述最后三个函数的定义,例如,如果我们要将一个对象赋值给另一个对象,编译器会提供赋值运算符的定义,可以看出Stringbad类中的问题是由隐式复制构造函数和隐式的赋值运算符引起的,因此,我们可以自己提供一个参数符合的复制构造函数,就不会出现这样的问题,也可以对赋值运算符进行显示的重载,防止其中的某个部分不能使用

对于复制构造函数的说明:

赋值运算符

对于赋值运算符重载的说明

应用实例

我们可以根据上面的知识将我们的所写的代码进行改进补充,重新体会类的各种用法,并完成一些字符串的基本操作

在构造函数使用new的注意事项

在构造函数使用new和delete注意事项如下:

有关返回对象的说明

当成员函数或者独立函数返回对象时,有几种返回方式可以选择,即可以返回对象的引用,指向对象的const引用或者const对象

返回指向const对象的引用

返回指向非const对象的引用

返回对象

总结

 

使用指向对象的指针

我们可以使用一个指针来指向一个类的对象,当我们使用对象指针时,需要注意以下几点:

定位new运算符

定位new运算符能够能够让我们在分配内存时指定内存的位置,但是,将定位new运算符用于类的情况却有所不同,我们下面通过一个测试的例子来看看

我们在这个程序中使用new定位运算符已经普通的new运算符来开辟内存空间,并且测试它们调用构造函数和析构函数的情况,运行代码结果如下:

我们可以看出,在这个例子中,我们的构造函数被调用了四次,而析构函数只被调用了一次,并且还出现了段错误,这个原因是什么呢?并且如何进行修改?

原因如下:

delete可以与常规的new运算符配合使用,但是不能与new运算符配合使用,因为常规new运算符开辟了内存空间,而定位new运算符是在别处开辟的内存空间

我们在使用类对象的指针时说过,当我们使用new去创建类的对象时,会去调用构造函数,只有当我们显式的去使用delete时,程序才会去调用析构函数,因为我们要修改后的代码为

delete []p;
delete p2;
delete p4;

程序运行后的结果为

此时我们可以看出,析构函数被调用了两次,即p2和p4调用了析构函数,因为delete [] p释放使用常规new运算符分配的整个内存块,但它并没有为定位new运算符在该内存块中创造的对象调用析构函数,因此,我们需要显式地为定位new运算符创建的对象调用析构函数,显示调用析构函数时,必须知道要销毁的对象,在我们添加上之后

delete p2;
delete p4;
p3->~A();
p1->~A();
delete [] p;

程序的运行结果如下所示:

在这里,我们可以看出,p3的C将原来p1里的A给覆盖掉了,这是因为我们两次使用new定位运算符时指向的内存空间的起始位置是一样的,所以后面p3调用时就会将原本的内容进行覆盖,要解决这个问题,我们只需要在p3使用new定位运算符时,让其进行偏移一个类的大小就可以解决

A *p3 = new(p + sizeof(A)) A("C",6);

提示:

成员初始化列表

当我们在类的私有成员里设置了一个const常量,那么我们就必须在构造函数的初始化列表中对其进行初始化,否则就会出错

对于我们的代码而言,num是一个常量,所以我们可以对其进行初始化,但是不能给它赋值,当我们调用构造函数时,对象会将在括号中的代码执行前就被建立,即我们没有进行a = anum;和num = anum + 1;操作之前,我们的程序就已经为a和num分配了内存空间,这个分配内存空间的过程实际就是相当于我们对a和num进行初始化的过程,只是我们没有给它们一个确定的值,而当我们开始执行a = anum;和num = anum + 1;时,我们进行的是常规的赋值操作,而不是初始化,因此,对于const数据成员,必须在执行到构造函数之前就对其进行初始化

C++提供了一种特殊的语法来完成这个过程,即成员列表初始化

成员初始化列表的要求如下

       

举报
0 条评论