第12章 类和动态内存分配
第12章 类和动态内存分配
然后,程序将headlinel 传递给cllmel()函数,并在调用后重新显示headline1。代码如下:
callmel (headlinel) :
cout << "headlinel: " << headlinel << endl;
下面是运行结果:
String passed by reference:
"Celery Stalks at Midnight"
headlinel: Celery Stalks at Midnight
这部分代码看起来也是正常的。
但是随后程序执行了如下代码:
callme2 (headline2) :
cout << "headline2: " << headline2 << endl:
这里,callme2()按值(而不是按引用)传递headline2,结果表明这是一个严重的问题!
String passed by value:
"Lettuce Prey"
"Lettuce Prey" object deleted. 2 left
headline2: D o
首先,将headline2作为函数参数来传递从而导致析构函数被调用。其次,虽然按值传递可以防止原始
参数被修改,但实际上函数已使原始字符串无法识别,导致显示一些非标准字符(显示的具体内存取决于
内存中包含的内容)。
请看输出结果,在为每一个创建的对象自动调用析构函数时,情况更糟糕:
End of main()
"Celery Stalks at Midnight" object deleted, 2 left
"Spinach Leaves Bowl for Dollars" object deleted, 1 left
"Spinach Leaves Bowl for Doll8" object deleted. 0 left
"@g" object deleted, -1 left
"-|" object deleted, -2 left
因为自动存储对象被删除的顺序与创建顺序相反,所以最先删除的3个对象是knots、sailor和 sport。
删除knots和 sailor时是正常的,但在删除 sport时,Dollars变成了Doll8。对于sport,程序只使用它来初
始化 sailor,但这种操作修改了sport。最后被删除的两个对象(headline2和headline1)已经无法识别。这
些字符串在被删除之前,有些操作将它们搞乱了。另外,计数也很奇怪,如何会余下-2个对象呢?
实际上,计数异常是一条线索。因为每个对象被构造和析构一次,因此调用构造函数的次数应当与析
构函数的调用次数相同。对象计数(num_strings)递减的次数比递增次数多2,这表明使用了不将 num_string
递增的构造函数创建了两个对象。类定义声明并定义了两个构造函数(这两个构造函数都使num_string递
增),但结果表明程序使用了3个构造函数。例如,请看下面的代码:
StringBad sailor = sports:
这使用的是哪个构造函数呢?不是默认构造函数,也不是参数为const char*的构造函数。记住,这种
形式的初始化等效于下面的语句:
StringBad sailor = StringBad (sports) : //constructor using sports
因为sports的类型为StringBad,因此相应的构造函数原型应该如下:
StringBad (const StringBad &) :
当您使用 …· 个对象来初始化另一个对象时,编译器将自动生成上述构造函数(称为复制构造函数,
因为它创建对象的一个副本)。自动生成的构造函数不知道需要更新静态变量num_string,因此会将计数
方案搞乱。实际上,这个例子说明的所有问题都是由编译器自动生成的成员函数引起的,下面介绍这一
主题。
12.1.2 隐式成员函数
StringBad类中的问题是由自动定义的隐式成员函数引起的,这种函数的行为与类设计不符。具体来说,
C++自动提供了下面这些成员函数:
● 默认构造函数,如果没有定义构造函数。
● 复制构造函数,如果没有定义。
383
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!