cpp: 自定义class中内存管理示例

通过自定义一个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 进行内存申请的),是不需要考虑内存管理的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值