析构函数: 类成员指向 new分配的内存,当类过期时,成员指针也将过期,但成员指向的内存仍被分配,除非使用 delete 将其释放;删除类可以释放类本身占用的内存,但并不能释放属于类对象成员指针所指向的内存,因为必须使用析构函数,在析构函数中使用 delete 语句,可以确保类过期时由构造函数使用 new 分配的内存被释放。
警告:new[] 对应 delete[]
深复制:两个独立的内存空间,值相同,如果类中包含了使用 new 初始化的指针成员,应当定义一个复制构造函数
浅复制:只是复制指针值和指针信息,没有额外开辟内存空间
hpp
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class StringBad {
char *str;
int len;
static int num;
public:
float f;
//构造函数
StringBad();
StringBad(const char *s);
//带实参构造函数
StringBad(const char *s = "dfsdaa", int i = 200)
{
len = i;
str = new char[strlen(s)+1];
strcpy(str, s);
}
//析构函数
~StringBad();
//friend function
friend ostream & operator<<(ostream & os ,StringBad & sb);
};
class Test {
public:
float f;
int i;
Test(const float a = 33.5f , int b = 999)
{
f = a;
i = b;
}
~Test()
{
cout << "~Test()" << endl;
}
void show(){ cout << f << endl << i << endl; };
};
cpp
int StringBad::num = 0;
#pragma mark - 构造函数
StringBad::StringBad()
{
len = 8;
str = new char[len+1];
strcpy(str, "C++");
cout << num++ << endl;
}
StringBad::StringBad(const char *s)
{
size_t i = strlen(s); //字符串长度,不包含最后的空白字符
str = new char[i+1];
strcpy(str, s); // str = s 错误,因为str是指针,不保存s字符串,s字符串保存在堆内存中,str只是指定内存地址的指针变量
num++;
cout << num << endl;
}
#pragma mark - 友元
ostream & operator<<(ostream & os , StringBad &sb)
{
os << sb.str << endl;
return os;
}
#pragma mark - 析构函数
StringBad::~StringBad()
{
cout << num-- << endl;
delete [] str;
}
main
#include <iostream>
#include "MemeryFile.hpp"
const int buffer = 512;
int main(int argc, const char * argv[]) {
StringBad *s;
Test *t1 , *t2 ,*t3 ,*t4;
char *buf = new char[buffer];
//1、定位new,在相邻的内存单元中创建两个对象
t1 = new (buf) (Test);
t2 = new (buf+sizeof(Test))(Test);
t1->show();
t2->show();
//2、常规new 运算
t3 = new Test();
t4 = new Test();
//释放内存
//定位new 需要手动调用析构函数
t1->~Test();
t2->~Test();
//常规new 的释放内存
delete t3;
delete t4;
//打印
/**
33.5
999
33.5
999
~Test()
~Test()
~Test()
~Test()
*/
return 0;
}