創建并初始化C++對象
當我們創建一個C++對象時,它需要占用一些內存,即使我們寫一個完全為空的類,類中沒有成員,什么也沒有,它至少也要占用一個字節的內存。但是我們類中有很多成員,它們需要存儲在某地方,當我們決定開始使用這個對象時,我們會創建一堆變量,對象有一堆變量,我們需要在電腦的某個地方分配內存,這樣我們就可以記住這些變量設置的值。
應用程序會將內存主要分為兩部分,棧和堆,還有其他部分的內存,比如源代碼的區域。
在C++中我們要選擇對象要放在哪里,對象是在棧上還是在堆上創建,它們有不同的功能差異。
棧:棧對象有一個自動的生存期,他們的生存期實際上是由它聲明的地方的作用域決定的,只要變量超出作用域,也就是說內存被釋放了,因為當作用域結束的時候,棧會彈出作用域里面的東西,棧上的任何東西會被釋放。
堆:一旦在堆中分配一個對象,實際上你已經在堆上創建了一個對象,它會一直待在那里,直到你做出決定,確定不需要它,想要釋放這個對象,那怎末處理這段內存都行。
?
代碼案例:
在棧上創建:?
在什么時候在棧上創建對象?
幾乎所有的時候,如果你能像這樣在棧上創建對象,那就像這樣創建對象,因為這是C++中最快的方法,也是可以管控的方法,去初始化對象
某些情況下不能這么做的原因?
1、如果將實例化對象放到main函數的生存期外
void Function(){int a = 2;Entity entity;}
一旦到達函數結尾的花括號,這個entity會從內存中被銷毀
當我們在main函數中調用Function時,就為這個函數創建了一個棧結構,它包含了我們聲明的所有局部變量,其中包括基本類型,也包括我們的類和對象,當函數結束時,棧幀會被銷毀,即棧上所有的內存,所有創建的變量都消失了
如果想讓括號{}內的實例化對象在作用域之外依然存在,就不能分配到棧上,需要使用堆分配。
2、如果entity的規模太大,可能有太多的entity,可能沒有足夠的空間在棧上分配,因為棧通常非常小,通常是1M/2M
# include <iostream>
# include <string>
using namespace std;class Entity
{
private:string m_Name; //只有一個成員,是一個字符串
public:Entity() : m_Name("Unknown") {}Entity(const string& name) : m_Name(name) {}const string& GetName() const { return m_Name; }
};int main()
{// 1、在棧上創建Entity entity; // 實際上調用了默認構造函數Entity() : m_Name("Unknown")cout << entity.GetName() << endl;Entity entity1("chen");// 等價于 Entity entity1 = Entity("chen")cout << entity1.GetName() << endl;/*在什么時候在棧上創建對象?幾乎所有的時候如果你能像這樣在棧上創建對象,那就像這樣創建對象,因為這是C++中最快的方法,也是可以管控的方法,去初始化對象某些情況下不能這么做的原因?1、如果將實例化對象放到main函數的生存期外void Function(){int a = 2;Entity entity;}一旦到達這個花括號,這個entity會從內存中被銷毀當我們調用Function時,就為這個函數創建了一個棧結構,它包含了我們聲明的所有局部變量,其中包括基本類型,也包括我們的類和對象,當函數結束時,棧幀會被銷毀,即棧上所有的內存,所有創建的變量都消失了Entity* e;{Entity entity2("cherno");e = &entity2;cout << entity2.GetName() << endl;} 一旦出了{}作用域,就到達了棧端,entity2對象就已經不存在了如果想讓括號{}內的實例化對象在作用域之外依然存在,就不能分配到棧上,需要使用堆分配cin.get();return 0;
}
在堆上創建:
在堆上創建,首先要做的就是在改變類型,將Entity改成Entity*,通過new關鍵字,這里最大的區別不是那個類型變成了指針,而是new關鍵字,new關鍵字是關鍵。
Entity* entity = new Entity("cherno");當我們調用new Entity時,會在棧上分配內存,調用構造函數,這個new Entity實際上會返回一個Entity*,它會返回entity在堆上被分配的內存地址。
使用new關鍵字必須調用delete釋放內存
delete + 變量名:delete entity;
性能問題:在堆上分配要比棧花費更長的時間,而且在堆上分配的話,您必須手動釋放被分配的內存
# include <iostream>
# include <string>
using namespace std;class Entity
{
private:string m_Name; //只有一個成員,是一個字符串
public:Entity() : m_Name("Unknown") {}Entity(const string& name) : m_Name(name) {}const string& GetName() const { return m_Name; }
};int main()
{// 2、在堆上創建/*在堆上創建,首先要做的就是在改變類型,將Entity改成Entity*,通過new關鍵字,這里最大的區別不是那個類型變成了指針,而是new關鍵字,new關鍵字是關鍵當我們調用new Entity時,會在棧上分配內存,調用構造函數,這個new Entity實際上會返回一個Entity*,它會返回entity在堆上被分配的內存地址*/Entity* entity = new Entity("cherno");//釋放內存//delete 變量名;delete entity;/*性能問題:在堆上分配要比棧花費更長的時間,而且在堆上分配的話,您必須手動釋放被分配的內存*/cin.get();return 0;
}
創建對象的兩種方法,如何選擇?
如果對象太大,或者需要顯示地控制對象的生存期,那就是用堆創建,其他情況就是用棧創建。