三大函數(shù):拷貝構(gòu)造梅割、拷貝賦值姊氓、析構(gòu)
class String
{
public:
String(const char* cstr = 0);
String(const String& str);
String& operator=(const String& str);
~ String();
char* get_c_str() const {return m_data;}
private:
char* m_data;
};
如果所寫的類中帶有指針,不能使用編譯器中自動(dòng)生成的拷貝構(gòu)造和拷貝賦值函數(shù)邀杏,必須自己重寫一個(gè)贫奠。
堆唬血、棧與內(nèi)存管理
重載的operator<<函數(shù)必須是一個(gè)函數(shù),不能寫成一個(gè)成員函數(shù)唤崭,因?yàn)槿绻麑懗沙蓡T函數(shù)拷恨,<<在使用的時(shí)候必須在cout的左側(cè)(<<cout)不符合用戶的使用習(xí)慣,因此需要將其寫成一個(gè)全局函數(shù)谢肾。
所謂stack(棧)腕侄,所謂heap(堆)
stack:
存在于某個(gè)作作用域的一塊內(nèi)存空間。在函數(shù)體內(nèi)聲明的任何變量芦疏,其所使用的內(nèi)存塊都取自stack
Heap:
指由操作系統(tǒng)提供的一塊global內(nèi)存空間冕杠,程序可動(dòng)態(tài)分配從某種獲得若干區(qū)塊。
local Object生命周期
class Complex{...};
...
{
Complex c1 (1, 2);
}
c1被自動(dòng)釋放
static local object生命周期
class Complex{...};
...
{
static Complex c1 (1, 2);
}
c2生命在作用域(scope)結(jié)束之后仍然存在酸茴,直到整個(gè)程序結(jié)束分预。
不帶指針類的new和delete
new:
其中的opreator new()是C++中定義的一個(gè)特殊函數(shù),在其內(nèi)部中是調(diào)用malloc(n)函數(shù)進(jìn)行內(nèi)存的分配的薪捍。
delete:
同樣的operator delete()是C++中的一個(gè)特殊函數(shù)笼痹,內(nèi)部調(diào)用的free
帶有指針類的new和delete
new:
delete:
調(diào)用析構(gòu)函數(shù)的時(shí)候,會(huì)釋放類中指針?biāo)嫉膬?nèi)存酪穿。
動(dòng)態(tài)分配所得到的內(nèi)存塊(memory block)凳干, in VC
上面圖片中,內(nèi)存分配較多的是在debug模式下分配的內(nèi)存被济。
橘色的部分是Cookie中存放的是內(nèi)存釋放時(shí)需要的信息救赐,綠色的部分是復(fù)數(shù)對(duì)象所占用的內(nèi)存,算出的內(nèi)存是52只磷,由于內(nèi)存的總數(shù)是16的倍數(shù)经磅,因而需要填充12bit的內(nèi)存,一共為64喳瓣。64寫成16進(jìn)制為00000040馋贤,由于是系統(tǒng)分配給對(duì)象的內(nèi)存,因此橘色部分是末尾數(shù)字為1畏陕,00000041
動(dòng)態(tài)分配所得的array
array new 一定搭配array delete
如果一個(gè)類中含有指針成員配乓,進(jìn)行array new之后,必須搭配使用array delete否則會(huì)產(chǎn)生內(nèi)存泄漏惠毁,其中泄漏的部分是犹芹,類中指針成員并沒(méi)有得到釋放,如果該類中不包含指針成員鞠绰,是不會(huì)造成內(nèi)存泄漏的腰埂。
第二周作業(yè)
#pragma once
#include <iostream>
class Shape
{
int no;
};
class Point
{
public:
Point(int x, int y) : x(x), y(y) {}
Point& operator=(const Point& point)
{
if (this == &point)
return *this;
this->x = point.x;
this->y = point.y;
}
~Point(){}
int getX() const { return this->x; }
int getY() const { return this->y; }
private:
int x;
int y;
};
class Rectangle : public Shape
{
int width;
int height;
Point * leftUp;
public:
Rectangle(int width, int height, int x, int y);
Rectangle(const Rectangle& other);
Rectangle& operator=(const Rectangle& other);
~Rectangle();
int GetWidth() const;
int GetHeight() const;
Point* GetPoint() const;
};
Rectangle::Rectangle(int width, int height, int x, int y)
{
this->width = width;
this->height = height;
leftUp = new Point(x, y);
}
Rectangle::Rectangle(const Rectangle & other)
{
this->width = other.width;
this->height = other.height;
this->leftUp = new Point(other.leftUp->getX(), other.leftUp->getY());
//this->leftUp = other.leftUp;
}
Rectangle& Rectangle::operator=(const Rectangle& other)
{
//判斷地址是否相同
if (this == &other)
return *this;
this->width = other.width;
this->height = other.height;
this->leftUp = new Point(other.leftUp->getX(), other.leftUp->getY());
// 這種寫法是錯(cuò)誤的,這種寫法會(huì)使得this->leftUp和other.leftUp指向同一個(gè)對(duì)象蜈膨,
//當(dāng)析構(gòu)的時(shí)候就會(huì)出現(xiàn)問(wèn)題,當(dāng)其中的一個(gè)指針指向的內(nèi)被釋放時(shí)屿笼,那么另外一個(gè)指針就會(huì)成為野指針牺荠,再delete會(huì)崩潰
//this->leftUp = other.leftUp;
return *this;
}
Rectangle::~Rectangle()
{
delete leftUp;
}
int Rectangle::GetWidth() const
{
return this->width;
}
int Rectangle::GetHeight() const
{
return this->height;
}
Point* Rectangle::GetPoint() const
{
return this->leftUp;
}
std::ostream& operator<<(std::ostream& os, const Rectangle& rec)
{
os << rec.GetWidth() << rec.GetHeight()
<< rec.GetPoint()->getX()
<< rec.GetPoint()->getY();
return os;
}
static
上圖中解釋了this指針,cout << c1.real(); this指針相當(dāng)于&c1驴一。調(diào)用非靜態(tài)成員函數(shù)休雌,this指向的即為該調(diào)用者。
其中double Account::m_rate = 8.0;為靜態(tài)成員變量的定義肝断。
該模式為單例模式杈曲,由于構(gòu)造函數(shù)是私有的,因而外界是不能創(chuàng)建對(duì)象的胸懈,成員A是靜態(tài)的担扑。
這種寫法相對(duì)上面的好處是,上面一種靜態(tài)變量一開始就占有著內(nèi)存趣钱,而第二種只有創(chuàng)建對(duì)象的時(shí)候才會(huì)開始占有內(nèi)存涌献。