动态内存分配、指针成员和析构函数
dynamic memory allocation,pointer members and destructors
为了理解复制构造函数、复制赋值操作符和析构函数是如何工作的,我编写了以下虚拟类:
#include <string>
#include <iostream>
class Box {
public:
// default constructor
Box(int i=10,const std::string &t=std::string()) : a(i),s(new std::string(t)) {}
// copy constructor
Box(const Box &other) { a=other.a; s=new std::string(*other.s); }
// copy assignment operator
Box &operator=(const Box &other) { a=other.a; s=new std::string(*other.s); }
// destructor
~Box() { std::cout<<"running destructor num. "<<++counter<<std::endl; }
int get_int() { return a; }
std::string &get_string() { return *s; }
private:
int a;
std::string *s;
static int counter;
};
int Box::counter=0;
我在代码中使用这个类类型来测试它是如何工作的,但我正在考虑销毁具有内置指针类型成员的对象的含义:
#include "Box.h"
using namespace std;
int main()
{
Box b1;
Box b2(2,"hello");
cout<<b1.get_int()<<" "<<b1.get_string()<<endl;
cout<<b2.get_int()<<" "<<b2.get_string()<<endl;
Box b3=b1;
Box b4(b2);
cout<<b3.get_int()<<" "<<b3.get_string()<<endl;
cout<<b4.get_int()<<" "<<b4.get_string()<<endl;
b1=b4;
cout<<endl;
cout<<b1.get_int()<<" "<<b1.get_string()<<endl;
{
Box b5;
} // exit local scope,b5 is destroyed but string on the heap
// pointed to by b5.s is not freed (memory leak)
cout<<"exiting program"<<endl;
}
该指针在构造函数中初始化,指向自由存储区动态分配的(总是新的)内存。因此,当调用析构函数时,要销毁的对象的成员按相反的顺序销毁。在这种情况下,只有int和指针对象被销毁,并且我最终有内存泄漏(堆上的字符串没有被释放),这是正确的吗?
此外,定义这个复制赋值操作符,每次赋值对象时是否都有内存泄漏(指针指向堆上的新对象,而前者丢失了,不是吗?)?
每次调用new时,都必须删除它(共享指针除外)。
所以必须在析构函数中删除字符串。
赋值操作符作用于一个已存在的实例,因此您已经创建了s,不必为s创建一个新的字符串。
析构函数析构它的成员。由于指针类似于int型,因此只有保存地址的变量被析构,而不是它所指向的对象。
所以,是的,你会有内存泄漏在每个对象中,每次你使用赋值操作符,你设计你的类的方式。
请记住,分配发生在基础构造、复制构造和赋值条件下
在析构函数和赋值时条件释放
需要注意的条件是:
x = x;
因此您的代码可以更改为以下模式(在您无法使用首选适当的智能指针的情况下)
Box(int i=10,const std::string &t=std::string()) : a(i),s(new std::string(t)) {}
// copy constructor
Box(const Box &other) { cp(other); }
// copy assignment operator
Box &operator=(const Box &other) {
if (&other != this) // guard against self assignment
{
rm();
cp(other);
}
return *this;
}
// destructor
~Box() { rm(); }
private:
void cp(const Box &other) {a=other.a; s=new std::string(*other.s);
void rm() {
std::cout<<"running destructor num. "<<++counter<<std::endl;
delete s; // prevents leaks
}
处理未命名动态分配成员的一种可能方法是每次创建成员时将它们保存在容器中(在对象,函数等中),然后在析构函数中运行for
循环,delete
语句后跟容器的元素。
你可以用vector:
vector <string*> container;
,你可以这样使用它:
// define it in the private members of your class
vector <string*> container;
// use it when you create the string
container.push_back(new dynamicallyAllocatedObject);
// free memory in the destructor
for(auto it = container.begin(); it != container.end(); ++it) delete *it;
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- C++成员的析构函数顺序与shared_ptr
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 工会成员的析构函数似乎是自动调用的
- 为什么类构造函数为其成员生成析构函数?
- C++类析构函数删除成员(如果"owner"?
- C++ 在析构函数调用之前删除的动态成员数组
- 如何从类成员函数返回指针,例如 size_t * class :: function(); 并使用类析构函数 ~size
- 在这种情况下,工会成员会调用自己的析构函数吗
- 在析构函数之后,围绕成员函数的C++lambda包装器是如何工作的
- C++ 将队列作为成员的类的构造函数和析构函数
- 是否可以访问类数据成员并在析构函数中对它们执行操作?
- 使用 std::function 作为成员函数,它捕获"this",并在析构函数之后从复制的 lam
- 如何在析构函数中执行一些代码*在*成员被销毁之后
- 应该在成员对象上调用析构函数
- 如何为包含map<int,*double>成员的类编写析构函数?
- 为什么在这里调用析构函数,以及在调用该对象析构函数后如何调用对象成员函数?
- 使用线程销毁类析构函数中的shared_ptr成员变量
- C++ 类析构函数删除部分但不是全部成员数据
- C++析构函数是否始终或仅在有时调用数据成员析构函数