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__
如果没有自检,那么在双指针指向同一块内存区域的情况下
-
一开始就会杀掉内存区域
-
第二个动作去动态开辟空间就无法获得大小长度