我正在为大学做一个项目,我试图找出如何正确删除内存,以及我想出的删除方式是否与使用智能指针具有相同的效果。
这是一个将容纳在公司和团队中工作的所有员工的类,这些员工基本上具有指向某些员工的指针向量。
class Company
{
private:
std::string companyInfo;
std::vector<Employee * > employees;
std::vector<Team *> teams;
public:
Company();
~Company();
std::string getCompanyInfo() const;
void setCompanyInfo(const std::string & companyInfo);
bool addEmployee(Employee * employee, const std::string & teamName);
bool addTeam(Team * team);
void printTeams() const;
void printEmployees() const;
};
所以我的问题是:这是释放内存的正确方法吗,如果是,它将提供与使用智能指针自动化该过程相同的结果。
Company::~Company()
{
for (Employee * e : employees) {
delete e;
}
employees.clear();
for (Team * t : teams) {
delete t;
}
teams.clear();
}
如果最好使用智能指针,我应该在我的特定情况下使用唯一或共享指针。我对智能指针有红色,它们会在范围结束时删除分配的内存,但我真的很困惑何时结束。当公司的析构者被召唤时,这会发生吗?
提前感谢,如果我的问题看起来很愚蠢,很抱歉。
如果你不知道自己在做什么,就不应该在你的代码逻辑中写delete
。这是规则。每当你违反这个规则时,都会期待各种各样的问题发生。换句话说:始终使用 std 容器 + 智能指针。
唯一指针:围绕指针的简单包装器,当它超出范围时,它将删除它下面的资源。你不能复制唯一的指针,因为如果可以的话,谁将拥有指针的所有权?谁将删除它?只有 1 个对象可以删除它。
共享指针:使复制成为可能,但代价是有一个(原子)计数器来计算有多少对象引用同一个指针。当计数器变为零时,指针下的资源将被删除。
这是释放内存的正确方法
假设容器中装满了像这样的new
运算符,
employees.push_back(new Employee());
teams.push_back(new Team());
那么是的,这是清理这些资源的正确方法。
。如果是,它将提供与使用智能指针自动化该过程相同的结果。
一般是的。您可以调整智能指针删除其管理的资源的工作方式,但默认行为是适合您的情况的正确行为(调用delete
)。
我应该使用唯一指针还是共享指针
第一选择应该是std::unique_ptr
.它比std::shared_ptr
更高效,并且对如何使用它所管理的对象更具限制性。但这会带来限制,例如,无法复制具有std::unique_ptr
数据成员(如您案例中的Company
)的类。相反,使用std::shared_ptr
可以缓解此问题,但具有非常不同的语义 - 复制Company
对象意味着共享团队和员工。这可能不是您想要的。解决此问题的一种方法是使用std::unique_ptr
,实现复制和复制赋值构造函数,Company
Employee::clone()
和Team::clone()
成员函数的虚拟构造函数。
当范围结束时,他们会删除分配的内存,但我真的很困惑何时结束
举个例子:
void someFunction()
{
Company c;
// stuff...
} // the scope ends here, ~Company will be called
这是释放内存的正确方法
析构函数是可以的,假设所有存储的指针都已使用 new-expression 进行分配,并假设所有指针仍然有效,即不悬空。
不过,清除向量是多余的。矢量是关于立即被销毁的,所以它们的元素无论如何都会被清除。
但是,您的类很可能已损坏。它是可复制的,如果您制作副本,并且不从其中一个副本中删除指针,那么这些对象的析构函数将删除相同的指针,这将导致未定义的行为。
您可以解决此问题,也可以通过使用智能指针使析构函数更简单(您可以简单地使用隐式析构函数)。
我应该使用唯一指针还是共享指针
是的,你应该。
您的代码演示了唯一的所有权 -Company
拥有唯一的Employee
和Team
- 因此最简单的更改是使用唯一的指针。
我对智能指针有红色,它们会在范围结束时删除分配的内存,但我真的很困惑何时结束。当公司的析构者被召唤时,这会发生吗?
它是删除指针的智能指针的析构函数。
当智能指针是局部变量时,它会在作用域的末尾销毁。就像您的Company
是局部变量一样,它在作用域结束时被销毁,并且其析构函数将被运行。
当智能指针是成员时,当超级对象被销毁时,它将被销毁。在您的情况下,您将有一个智能指针向量,在这种情况下,当向量被销毁时,智能指针将被销毁,或者智能指针从矢量中删除。