c++中,構造對象實例有兩種方式,一種返回對象實例,一種返回該對象實例的指針。如下所示:
一、兩種返回值
RedisConn conn1; //得到實例conn1;RedisConn *conn2 = new RedisConn();//得到指針conn2;RedisConn conn3 = new RedisConn();//錯誤,類型不匹配
意思是說,RedisConn conn;就是構造了一個實例,而通過new方式的話,就是返回指針。太奇怪了,跟c#、java完全不一樣啊。在c#或java中,RedisConn conn意味著conn沒有賦值,new RedisConn()返回一個誠實可靠的實例。
二、后續兩種不同的處理方式
1、構造于棧
RedisConn conn;
這種方式下,conn 是在棧(stack)上分配的。棧是由編譯器自動管理的內存區域,用于存儲局部變量。conn 的生命周期與它的作用域相關聯。當程序執行離開定義 conn 的代碼塊時(比如函數結束),conn 會被自動銷毀,其析構函數會自動調用。
這種方式的話,如果想訪問它的成員函數和成員變量,通過"."號,比如conn.rec_cnt;
void function() {RedisConn conn; // 在棧上創建一個 RedisConn 實例conn.someMethod(); // 直接調用方法
} // 當函數結束時,conn 自動被銷毀
優點:
自動管理內存,無需手動釋放。
簡單易用,適合于局部使用的小型對象。
缺點:
棧上的空間有限,不適合創建大型對象或需要長時間存在的對象。
對象的生命周期受限于其作用域。
2、構造于堆
RedisConn* conn = new RedisConn();
內存分配:new RedisConn() 在堆(heap)上為 RedisConn 對象分配內存,并返回指向該對象的指針。
生命周期:堆上的對象不會隨著作用域的結束而自動銷毀。你需要顯式地調用 delete 來釋放這塊內存,否則會導致內存泄漏。
訪問方式:通過 -> 操作符來訪問指針所指向的對象的成員函數和成員變量。
void function() {RedisConn* conn = new RedisConn(); // 在堆上創建一個 RedisConn 實例conn->someMethod(); // 使用 -> 操作符調用方法// 記得釋放內存delete conn;conn = nullptr; // 設置為 nullptr 避免懸掛指針
}
優點:
可以動態控制對象的生命周期,適合于需要長時間存在或大小不確定的對象。
堆上的空間相對較大,適合創建大型對象。
缺點:
需要手動管理內存,增加了出錯的可能性(如忘記釋放內存導致內存泄漏)。
分配和釋放堆上的內存通常比棧上的操作更慢。
三、堆和棧
1、棧(Stack)
后進先出。
2、堆(Heap)
特殊的完全二叉樹結構,存進去,自然而然得到一個位置,比如它的子節點都比它小,形成一個小山包(小土堆);或者反過來,它所有兒子都比它大。所以堆查找最大值最為快速。有最大堆,最小堆。沒有好大堆。
二叉樹的概念我已經忘得一干二凈,依稀記得有一種二叉樹是:
左邊的子節點都比它小,右邊的子節點都比它大
這種跟堆沒有啥關系,這叫二叉搜索樹,排過序的,便于搜索。
與堆相對應,可能是坨,完全沒有順序可言。