類的普通構造函數: 函數名與類名一樣的函數;
拷貝構造函數:函數名與類名一樣 參數也是類的類型;
析構函數:~String(void) delete 刪除構造函數;
賦值構造函數:重載運算符= 關鍵字(operator)
//析構函數是默認最後執行的,與它所存在的位置無關
在內存管理中,都是指針(靜態)存在棧裏面,申請的空間(非靜態)存在堆中;
內存分配方式有三種:
(1) 從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的
整個運行期間都存在。例如全局變量,static 變量。
(2) 在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函
數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集
中,效率很高,但是分配的內存容量有限。
(3) 從堆上分配,亦稱動態內存分配。程序在運行的時候用 malloc 或 new 申請任意
多少的內存,程序員自己負責在何時用 free 或 delete 釋放內存。動態內存的生存
期由我們決定,使用非常靈活,但問題也最多。
int a={1,2,3};
int *p;
p=a;
free:釋放後還會存在首地址的儲存p=a;釋放的不夠乾淨;
delete:釋放後會p=0;釋放的更加乾淨
#pragma once
#include <iostream>
class String
{
public:
String(); //默認構造函數
String(const char *str = NULL); // 普通構造函數
String(const String &other); // 拷貝構造函數
~String(void); // 析構函數
String & operator = (const String &other); // 賦值函數
private:
char *m_data; // 用於保存字符串
};
#include "Microsoft.h"
// String 的析構函數
String::~String(void)
{
delete[] m_data;
//由於 m_data 是內部數據類型,也可以寫成 delete m_data;
}
// String 的普通構造函數
String::String(const char *str)
{
if (str == NULL)
{
m_data = new char[1]; //若能加 NULL判斷則更好;
*m_data = '\0';
}
else
{
int lenth = strlen(str);
m_data = new char[lenth+1]; //若能加 NULL 判斷則更好
strcpy(m_data,str);
}
}
// 拷貝構造函數
String::String(const String &other)
{
int length = strlen(other.m_data);
m_data = new char[length+1]; //若能加 NULL 判斷則更好
strcpy(m_data, other.m_data);
}
// 賦值函數
String & String::operator = (const String &other)
{
// 1. 檢查自賦值;
if (this == &other)
{
return *this;
}
// 2. 釋放原有的內存資源;
delete[] m_data;
// 3. 分配新的內存資源, 並複製內容;
int length = strlen(other.m_data);
m_data = new char[length + 1];
strcpy(m_data, other.m_data);
// 4. 返回本對象的引用;
return *this;
}