在我的大学里,有一个用 C++ 进行的实用编程测试——我遇到了一个例子,我不确定所讨论的任务是否有效并且是否可以正确完成。
(简单)任务:
完成 的析构函数
Person
,以便name
再次释放分配的在 main 函数中,替换
//???
为释放先前分配的内存所需的语句
起初,这些任务对我来说似乎微不足道:对于析构函数,只需编写delete[] name
并在 main 函数中使用delete[] friends
. 大概这也是这个例子的作者想要我们做的。
然而:
此代码示例中似乎存在缺陷,导致内存泄漏以及多次调用析构函数。
person 类没有赋值operator =
,这意味着由于现有的 Person 对象如maria
被分配到 main 函数中的数组中的槽friends
,内部分配name
的 s 不会被复制。所以现在两个对象共享同一个内部char*
指针!此外,指向Person
先前驻留在所述数组槽中的名称的指针永久丢失,导致不可避免的内存泄漏。
正如delete[] friends;
所谓的 - 数组中的对象被销毁 - 导致它们的析构函数被调用并释放它们的name
成员。但是,当程序结束时,范围内的本地 Person 对象main
被破坏 - 当然它们的name
成员仍然指向之前已经释放的内存。
实际问题:
- 这个测试示例有缺陷,还是我遗漏了什么?
- 如果完全坚持执行给定的任务(仅更改析构函数的实现,并在主函数的注释部分插入新代码),是否可以解决上面列出的问题?
..
#include <iostream>
using namespace std;
int strlen(const char *str) {
if (str==0) return 0;
int i=0;
for (; str[i]; ++i);
return i;
}
void strcpy(const char *src, char *dest) {
if (src==0 || dest==0) return;
int i=0;
for (; src[i]; ++i) dest[i]=src[i];
dest[i]=’\0’;
}
class Person {
char *name;
public:
Person(const char *str = "Susi") {
name = new char[strlen(str)+1];
strcpy(str,name);
}
Person(const Person &p) {
name = new char[strlen(p.name)+1];
strcpy(p.name,name);
}
~Person() {
//...
}
void change() {
name[4]='e';
}
ostream &print(ostream &o) const {
o<<name;
return o;
}
};
int main() {
Person maria("Maria"), peter("Peter"), franz("Franz"), luisa("Luisa");
Person mary(maria);
Person luise;
Person p(luise);
Person *friends= new Person[7];
friends[0]=maria;
friends[1]=peter;
friends[2]=franz;
friends[3]=luisa;
friends[4]=mary;
friends[5]=luise;
friends[6]=p;
friends[5]=luisa;
friends[3].change();
friends[4].change();
for (int i=0; i<7; ++i) {
friends[i].print(cout);
cout<<endl;
}
//???
return 0;
}