通过自定义一个String
类来表示内存管理在自定义类中需要处理的地方。
//
// Created by cat on 2018/1/2.
//
#ifndef CPP02_STRINGBAD_H
#define CPP02_STRINGBAD_H
class StringBad {
private:
char *str;
unsigned int len;
static int nums;
static bool DEBUG_LIFESTYLE;
static bool DEBUG_OPERATOR;
public:
StringBad();
StringBad(const char *str);
StringBad(const StringBad &obj); // 复制构造
virtual ~StringBad();
friend std::ostream &operator<<(std::ostream &os, const StringBad &obj);
StringBad& operator=(const StringBad &obj);
};
#endif //CPP02_STRINGBAD_H
//
// Created by cat on 2018/1/2.
//
#include <cstring>
#include <iostream>
#include "StringBad.h"
int StringBad::nums = 0;
bool StringBad::DEBUG_LIFESTYLE = true;
bool StringBad::DEBUG_OPERATOR = true;
StringBad::StringBad() {
this->str = new char[1]; // 为什么要 new char[] ,为了和析构函数的 delete [] str 对应!
this->str[0] = '\0';
this->len = 0;
if (StringBad::DEBUG_LIFESTYLE) {
std::cout << StringBad::nums << "." << str << "|create..\n";
}
StringBad::nums++;
}
StringBad::StringBad(const char *str) {
size_t len = std::strlen(str);
this->len = (unsigned int) len;
this->str = new char[this->len + 1];
std::strncpy(this->str, str, this->len + 1);
if (StringBad::DEBUG_LIFESTYLE) {
std::cout << StringBad::nums << "." << str << "|create##\n";
}
StringBad::nums++;
}
StringBad::StringBad(const StringBad &obj) { // 复制构造函数 在 StringBad sb1 = sb2; 的时候调用
this->len = obj.len;
this->str = new char[this->len + 1];
std::strncpy(this->str, obj.str, this->len + 1);
if (StringBad::DEBUG_LIFESTYLE) {
std::cout << StringBad::nums << "." << str << "|create^^\n";
}
StringBad::nums++;
}
StringBad::~StringBad() {
StringBad::nums--;
delete[]this->str;
if (StringBad::DEBUG_LIFESTYLE) {
std::cout << StringBad::nums << "*" << str << "|release..\n";
}
}
std::ostream &operator<<(std::ostream &os, const StringBad &obj) {
os << obj.str << "|toString()\n";
return os;
}
StringBad &StringBad::operator=(const StringBad &obj) { // 赋值运算符 在 sb1 = sb2; 的时候调用
if (StringBad::DEBUG_OPERATOR) {
std::cout << str << ":operator=\n";
}
if (this == &obj) {
return *this; // 如果是把自己赋值给自己,就直接返回自己
}
delete[]this->str; // 释放之前的
this->len = obj.len;
this->str = new char[this->len + 1]; // 申请新的
std::strncpy(this->str, obj.str, this->len + 1);
return *this;
}
#include <iostream>
#include "StringBad.h"
using namespace std;
void callStr(StringBad &sb);
void callStr2(StringBad sb);
int main() {
const char *s1 = "比亚迪车主";
const char *s2 = "东郭灰猫";
const char *s3 = "南郭竽";
StringBad sb(s1); // create##
StringBad sb2 = sb; // create^^
StringBad sb3 = s2; // create##
StringBad ss = s3; // create##
cout << sb;
cout << sb2;
cout << sb3;
callStr(sb);
callStr2(sb3); // create^^ , 因为是按值传递的,所以是数据的拷贝
ss = sb3; // operator=
StringBad strBad; // create..
std::cout << "done." << endl;
return 0;
}
void callStr(StringBad &sb) {
cout << "callStr:" << sb;
}
void callStr2(StringBad sb) {
cout << "callStr2:" << sb;
}
输出效果:
0.比亚迪车主|create##
1.比亚迪车主|create^^
2.东郭灰猫|create##
3.南郭竽|create##
比亚迪车主|toString()
比亚迪车主|toString()
东郭灰猫|toString()
callStr:比亚迪车主|toString()
4.东郭灰猫|create^^
callStr2:东郭灰猫|toString()
4*东郭灰猫|release..
南郭竽:operator=
4.|create..
done.
4*|release..
3*东郭灰猫|release..
2*东郭灰猫|release..
1*比亚迪车主|release..
0*比亚迪车主|release..Process finished with exit code 0
结合log及输出,可以看出内存管理的必要性,在自定义类中。特别是需要重写“复制构造函数”以及operator=()
赋值操作符的重载。
不过,对于成员不需要内存管理的类(类成员没有需要主动使用new/malloc 进行内存申请的),是不需要考虑内存管理的。