1. 程式人生 > >動態記憶體管理常見面試題

動態記憶體管理常見面試題

一 、 malloc/free和new/delete異同點

共同點:都是從堆上開闢空間,最後都需要手動釋放
不同點:

  1. malloc/delete是標準庫函式,new/delete是操作符
  2. new建立物件時會呼叫建構函式+開空間 ;delete會呼叫解構函式,而malloc/free只會開空間,而不會呼叫建構函式和呼叫解構函式
  3. malloc/free需要手動計算型別大小且返回值是 void*,在使用時必須強轉 ,而new/delete可以自動計算空間並且返回對應型別的指標。
  4. malloc申請空間失敗時返回NULL,因此在申請完之後必須判空,new不需要,但是new有出錯會有異常捕獲
  5. malloc申請的空間一定在堆上,new不一定(也有可能會在棧上),因為operator new函式可以重新實現
  6. 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;
}

在這裡插入圖片描述