【发布时间】:2018-03-29 18:50:42
【问题描述】:
我一直在阅读有关delete[]、new[]、what-is-the-rule-of-three、
deallocating-objects-stored-in-a-vector, delete-vector-class-member 遇到了一个
抛出异常:读取访问冲突。
我已经定义了一个基类
class Person
{
private:
std::string name;
int age;
static int cur_id;
public:
Person() {}
Person(std::string new_name, int new_age) : name(new_name), age(new_age) { cur_id += 1; }
virtual ~Person() {}
void setname(std::string name) { this->name = name; }
std::string getname() { return name; }
int getage() { return age; }
void setage(int age) { this->age = age; }
int get_id() { return cur_id; }
virtual void getdata(void) = 0;
virtual void putdata(void) = 0;
};
派生类
class Professor : private Person
{
private:
int publications;
Professor* prof;
public:
Professor() {}
Professor(std::string new_name, int new_age, int new_pubs) : Person(new_name, new_age) { this->publications = new_pubs; }
~Professor() override { delete prof; }
void getdata() override
{
std::vector<std::string> prof_input = get_input();
std::cout << prof_input[0] << "\n";
std::cout << std::stoi(prof_input[1]) << "\n";
std::cout << std::stoi(prof_input[2]) << "\n";
prof = new Professor(prof_input[0], std::stoi(prof_input[1]), std::stoi(prof_input[2]));
}
void putdata() override
{
std::cout << prof->getname() << " " << prof->getage() << " " << prof->publications << " " << prof->get_id();
}
};
并且已经定义了main
int main()
{
int size;
std::cin >> size;
std::cin.ignore();
Professor* prof = new Professor();
std::vector<Professor> prof_vec;
for (int i = 0; i < size; i++)
{
int which;
std::cin >> which;
std::cin.ignore();
switch (which)
{
case 1:
{
prof->getdata();
prof_vec.push_back(*prof);
}
break;
case 2:
{
// something else
}
break;
}
}
for (auto prof : prof_vec)
{
prof.putdata();
} <<< ------------------- Things so south here
delete prof;
fgetc(stdin);
return 0;
}
我想发生的事情是(假设向量中只有一个元素),一旦对putdata() 的调用退出该块,析构函数调用delete prof 就会发生
this->prof 是 0xCDCDCDCD。
我正在尝试删除一个不存在的对象。如果我想确保正确delete,即使是这样一个简单的例子,我应该怎么做才能确保没有内存泄漏?
【问题讨论】:
-
如果你真的想以现代 C++ 方式确保没有内存泄漏,请使用smart pointer(链接很老,c++11 的智能指针被命名为
std::unique_ptr)。 -
@spectras 我完全同意你的看法。我的示例是为学习正确的内存管理而设计的,但我会在心跳中使用
std::unique_ptr、std::shared_ptr和std::make_unique()或std::make_shared() -
好的。在您的程序中,
for (auto prof : prof_vec)在迭代时为每个教授制作一个临时副本。这是可能的,因为您没有禁用复制构造函数,并且您的类具有默认构造函数并且只有微不足道的非静态成员。除了编译器生成的复制构造函数只是简单地复制指针,这必然会出错。如果您不想复制它们,请使用for (auto & prof : prof_vec)。并禁用该复制构造函数,您还将捕获 push_back() 副本。 -
请阅读minimal reproducible example。这段代码的绝大部分与问题完全无关。
-
你不应该有
Professor* prof;作为教授的班级成员,这完全没有意义。相反,getdata()函数应该初始化当前实例。
标签: c++ c++11 memory-management memory-leaks delete-operator