動態記憶體管理常見面試題
阿新 • • 發佈:2018-12-19
一 、 malloc/free和new/delete異同點
共同點:都是從堆上開闢空間,最後都需要手動釋放
不同點:
- malloc/delete是標準庫函式,new/delete是操作符
- new建立物件時會呼叫建構函式+開空間 ;delete會呼叫解構函式,而malloc/free只會開空間,而不會呼叫建構函式和呼叫解構函式
- malloc/free需要手動計算型別大小且返回值是 void*,在使用時必須強轉 ,而new/delete可以自動計算空間並且返回對應型別的指標。
- malloc申請空間失敗時返回NULL,因此在申請完之後必須判空,new不需要,但是new有出錯會有異常捕獲
- malloc申請的空間一定在堆上,new不一定(也有可能會在棧上),因為operator new函式可以重新實現
- new/delete比malloc/free效率要低,因為new/delete底層封裝的是malloc/free。
二 、設計一個類,該類只能在堆上建立物件
分析:我們在用在函式內部定義變數----是在棧上開闢空間,若在全域性區建立變數------則在資料段開闢空間
我們唯一知道能在堆上建立變數只有malloc相關函式,但是,malloc不會呼叫建構函式,pass。
那麼我們到底要怎麼做呢?
1.將建構函式作為私有成員,拷貝構造申明為私有成員,防止其他人呼叫在棧上建立物件
2. 提供一個靜態的成員函式,在該靜態成員函式中完成堆物件的建立
class Test { public: static Test* CreatObj() { return new Test; } private: //將建構函式申明為私有 Test() {}; //防拷貝,但是這樣是存在一個缺陷的,如果類中有friend函式該做法就會失效 //這裡我們只宣告,不實現。因為實現可能會很麻煩,而我們本身可能不需要 Test(const Test&t); //C++11提供的完美解決辦法----刪除函式 Test(const Test&t) = delete; private: int _data; }; int main() { Test *pt = Test::CreatObj(); /*Test obj; Test obj3(*pt);*/ return 0; }
三 請設計一個類,該類只能在棧上建立物件
這個就比較簡單了,只能在棧上建立物件,即不能再對上建立物件,這樣的話我們只需要將new的功能遮蔽掉即可,當然operator new 和 定位new表示式也會隨之遮蔽。
class StackType { public: static StackType CreatStackObj() { StackType obj; return obj; } void Print() { cout << "StackType::Print()" << endl; } private: StackType() {} //將operator new 和 定位new表示式 功能遮蔽 void* operator new(size_t n) = delete; void operator delete(void* p) = delete; }; int main() { StackType::CreatStackObj().Print(); // 相當於一個類 StackType obj = StackType::CreatStackObj(); obj.Print(); return 0; }