Class with pointer member(s) -> 带指针的类

Class with pointer member(s) -> 带指针的类

String字符串为讲解对象

设计一个Class先设计头文件

示例代码:

#pragma once

// 防卫式声明
#ifndef __STRING__
#define __STRING__

#include <string.h>

// 头文件定义
class String
{
public:
// 设计构造函数 -> 这里只是定义了函数接口.并没有实现
String(const char* cstr = 0);
String(const String& str); // 接收自己为参数,所以是拷贝构造
String& operator=(const String& str);
~String(); // 析构函数 -> 当类死亡的时候(离开他的作用域)析构函数就会被调用
// 成员函数 -> 因为不去改变m_data的值,所以一定要加上const
char* get_c_str() const { return m_data; }
private:
// 指向字符的指针
char* m_data;
};

inline
String::String(const char* cstr = 0)
{
// 检查是否传入空指针
if (cstr)
{
// 分配内存空间
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else
{
// 空指针也要返回一个空字符串 -> \0为最后一位
m_data = new char[1]; // 放置结束符号
*m_data = '\0';
}
}

// 定义析构函数
inline
String::~String()
{
// 清理动态分配的内存
delete[] m_data;
}

#endif // !__STRING__

浅拷贝

赋值操作直接改变指针,会造成原本指向两块的指针指向同一块区域,另一块区域没有指针指向.会导致内存泄漏

需要的是开辟一块内存区域存储值

示例代码:

#pragma once

// 防卫式声明
#ifndef __STRING__
#define __STRING__

#include <string.h>

// 头文件定义
class String
{
public:
// 设计构造函数 -> 这里只是定义了函数接口.并没有实现
String(const char* cstr = 0);
String(const String& str); // 接收自己为参数,所以是拷贝构造
String& operator=(const String& str); // s2 = s1,作用的是s2,那么s2就要先自毁,自毁完了以后在创建一个和s1一样大的内存空间进行拷贝
~String(); // 析构函数 -> 当类死亡的时候(离开他的作用域)析构函数就会被调用
// 成员函数 -> 因为不去改变m_data的值,所以一定要加上const
char* get_c_str() const { return m_data; }
private:
// 指向字符的指针
char* m_data;
};

inline
String::String(const char* cstr = 0)
{
// 检查是否传入空指针
if (cstr)
{
// 分配内存空间
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else
{
// 空指针也要返回一个空字符串 -> \0为最后一位
m_data = new char[1]; // 放置结束符号
*m_data = '\0';
}
}

inline
String::String(const String& str)
{
// 动态分配内存
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}

inline
String& String::operator=(const String& str)
{
// 自检 -> 这里的this是指调用者 -> 运算符作用的对象 -> 很关键
if (this == &str)
{
return *this;
}

// 先自毁
delete[] m_data;
// 重新分配内存
m_data = new char[strlen(str.m_data) + 1];
// 拷贝内容 -> 后者拷贝给前者
strcpy(m_data, str.m_data);
return *this;
}

// 定义析构函数
inline
String::~String()
{
// 清理动态分配的内存
delete[] m_data;
}

#endif // !__STRING__

如果没有自检,那么在双指针指向同一块内存区域的情况下

  • 一开始就会杀掉内存区域

  • 第二个动作去动态开辟空间就无法获得大小长度

posted @ 2024-03-28 19:24  俊king  阅读(29)  评论(0)    收藏  举报