最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++定制刪除器與特殊類設(shè)計(jì)(餓漢和懶漢)

 更新時(shí)間:2023年07月03日 10:09:28   作者:朵貓貓.  
這篇文章主要給大家介紹了關(guān)于C++定制刪除器與特殊類設(shè)計(jì)的相關(guān)資料,使用餓漢模式和懶漢模式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

定制刪除器

我們?cè)谏弦黄恼轮兄v到了智能指針,相信大家都會(huì)有一個(gè)問題,智能指針該如何辨別我們的資源是用new int開辟的還是new int[]開辟的呢,要知道[]必須與delete[]匹配否則會(huì)有未知錯(cuò)誤的,這個(gè)問題我們就交給定制刪除器來解決:

int main()
{
	shared_ptr<int> sp1(new int[10]);
	shared_ptr<string> sp2(new string[10]);
	return 0;
}

 比如上面的代碼,一旦運(yùn)行就會(huì)立即引發(fā)崩潰,這是因?yàn)閟hared_ptr默認(rèn)的釋放方式是delete而不是delete[]。

 我們從文檔中可以看到shared_ptr有一個(gè)模板參數(shù)是del,這個(gè)參數(shù)其實(shí)就是定制刪除器,為了解決釋放資源的問題。

template <class T>
struct DeleteArray
{
	void operator()(const T* ptr)
	{
		delete[] ptr;
		cout << "delete[]" <<ptr<< endl;
	}
};
int main()
{
	shared_ptr<int> sp1(new int[10],DeleteArray<int>());
	shared_ptr<string> sp2(new string[10],DeleteArray<string>());
	return 0;
}

 我們可以看到定制刪除器非常簡單,實(shí)際上就是一個(gè)仿函數(shù),當(dāng)我們將這個(gè)仿函數(shù)傳給shared_ptr,shared_ptr會(huì)在它的構(gòu)造函數(shù)中接收到這個(gè)仿函數(shù),然后析構(gòu)的時(shí)候就直接調(diào)用這個(gè)仿函數(shù)了。下面我們看看運(yùn)行結(jié)果:

可以看到是能成功釋放的,不再像之前那樣由于new和delete不匹配導(dǎo)致崩潰。當(dāng)然,這里既然是直接傳給構(gòu)造函數(shù)的,那么我們完全可以不用再寫仿函數(shù)了,直接用lambda會(huì)更加的方便,如下所示:

int main()
{
	shared_ptr<int> sp1(new int[10], [](const int* ptr)
		{
			delete[] ptr;
			cout << "delete[] ptr :" << ptr << endl;
		});
	shared_ptr<string> sp2(new string[10], [](const string* ptr)
		{
			delete[] ptr;
			cout << "delete[] ptr(string) :" << ptr << endl;
		});
	return 0;
}

可以看到這樣也是沒有問題的如果不是要打印演示的話會(huì)比第一種方式更加的簡潔,但是我們也說過lambda表達(dá)式的底層就是仿函數(shù)所以其實(shí)也差不了多少。當(dāng)然我們不僅可以釋放資源,還可以關(guān)閉文件:

shared_ptr<FILE> sp3(fopen("test", "w"), [](FILE* fp) { fclose(fp); });

下面我們也給自己的shared_ptr搞一個(gè)定制刪除器模板:

首先我們自己是不能像庫里面那樣直接將定制刪除器傳給構(gòu)造函數(shù)的,因?yàn)閹炖锩娴膕hared_ptr有好幾個(gè)類,所以可以直接給構(gòu)造函數(shù)加一個(gè)模板來傳定制刪除器。那么我們?cè)撊绾谓鉀Q呢?其實(shí)很容易因?yàn)槲覀兙鸵粋€(gè)shared_ptr類,所以只需要給這個(gè)類多一個(gè)模板參數(shù)就可以了。

namespace sxy
{
	template <class T>
	struct Delete
	{
		void operator()(T* ptr)
		{
			delete ptr;
		}
	};
	template <class T, class D = Delete<T>>
	class shared_ptr
	{
	public:
		//保存資源
		shared_ptr(T* ptr = nullptr)
			:_ptr(ptr)
			, _pcount(new int(1))
			, _pmtx(new mutex)
		{
		}
		//拷貝構(gòu)造
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount)
			, _pmtx(sp._pmtx)
		{
			_pmtx->lock();
			++(*_pcount);
			_pmtx->unlock();
		}
		void Release()
		{
			bool flag = false;
			_pmtx->lock();
			if (--(*_pcount) == 0)
			{
				_del(_ptr);
				delete _pcount;
				flag = true;
			}
			_pmtx->unlock();
			if (flag)
			{
				delete _pmtx;
			}
		}
		//賦值重載
		//..........
		//釋放資源
		~shared_ptr()
		{
			Release();
		}
		//像指針一樣
		//..............
	private:
		T* _ptr;
		int* _pcount;
		mutex* _pmtx;
		D _del;
	};
}

 我們這里默認(rèn)的是delete,當(dāng)然也可以自己模板特化一個(gè)delete[],我們就不再演示了。下面我們先運(yùn)行起來:

 沒有問題,我們?cè)僮约簜饕粋€(gè)[]的試一下:

int main()
{
	sxy::shared_ptr<int,DeleteArray<int>> sp1(new int[10]);
	sxy::shared_ptr<string,DeleteArray<string>> sp2(new string[10]);
	return 0;
}

 可以看到運(yùn)行起來也是沒有問題的,但是我們實(shí)現(xiàn)的定制刪除器是不可以傳lambda表達(dá)式的,這是因?yàn)閘ambda表達(dá)式無法作為一個(gè)參數(shù)類型。

注意:unique_ptr也和我們自己設(shè)計(jì)的刪除器一樣,都是不可以用lambda表達(dá)式的,這里大家可以自行去驗(yàn)證。

一、設(shè)計(jì)一個(gè)只能在堆上(或棧上)創(chuàng)建的類

我們?cè)谠O(shè)計(jì)只能在堆上創(chuàng)建的類之前,先設(shè)計(jì)一個(gè)不能被拷貝的類,因?yàn)楹竺娴念惗紩?huì)用到不能被拷貝的特點(diǎn)。

拷貝只會(huì)放生在兩個(gè)場景中:拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載,因此 想要讓一個(gè)類禁止拷貝, 只需讓該類不能調(diào)用拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載即可。 C++98 將拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載只聲明不定義,并且將其訪問權(quán)限設(shè)置為私有即可。

class BanCopy
{
    // ...
private:
    BanCopy(const BanCopy& bc);
    BanCopy& operator=(const BanCopy& bc);
    //...
};

原因:

1. 設(shè)置成私有:如果只聲明沒有設(shè)置成 private ,用戶自己如果在類外定義了,就可以不 能禁止拷貝了

2. 只聲明不定義:不定義是因?yàn)樵摵瘮?shù)根本不會(huì)調(diào)用,定義了其實(shí)也沒有什么意義,不寫 反而還簡單,而且如果定義了就不會(huì)防止成員函數(shù)內(nèi)部拷貝了。 C++11引入了delete關(guān)鍵字要禁用某個(gè)函數(shù)就更加的方便了:

C++11 擴(kuò)展 delete 的用法, delete 除了釋放 new 申請(qǐng)的資源外,如果在默認(rèn)成員函數(shù)后跟上 =delete ,表示讓編譯器刪除掉該默認(rèn)成員函數(shù)。

class BanCopy
{
    // ...
private:
    BanCopy(const BanCopy& bc) = delete;
    BanCopy& operator=(const BanCopy& bc) = delete;
    //...
};

下面我們思考如何實(shí)現(xiàn)只能在堆上創(chuàng)建的類,首先如果只能在堆上創(chuàng)建那么我們肯定是不能直接用構(gòu)造函數(shù)創(chuàng)建對(duì)象的,所以要把構(gòu)造函數(shù)私有,其次如果將一個(gè)堆上的對(duì)象拷貝給棧上的對(duì)象也不符合要求,所以拷貝構(gòu)造肯定也要禁掉,下面我們實(shí)現(xiàn)一下:

class HeapOnly
{
public:
	static HeapOnly* CreatObj() 
	{
		return new HeapOnly;
	}
	void print()
	{
		cout << "print()" << endl;
	}
private:
	HeapOnly()
	{}
	HeapOnly(const HeapOnly&) = delete;
};
int main()
{
	HeapOnly* hp = HeapOnly::CreatObj();
	hp->print();
	return 0;
}

可以看到我們將構(gòu)造函數(shù)設(shè)為私有,這樣就不會(huì)有隨意的對(duì)象被創(chuàng)建,只能通過我們的creat函數(shù)接收在堆上開辟的對(duì)象,注意我們的Creat接口一定是靜態(tài)的,因?yàn)槲覀儗?gòu)造封掉了沒有這個(gè)類的對(duì)象,如果不設(shè)置為靜態(tài)的那么誰來調(diào)用這個(gè)接口呢,其次我們還有禁掉拷貝構(gòu)造,為了防止下面這種情況:

HeapOnly ht(*hp);

對(duì)于賦值重載來講我們是沒必要考慮的,因?yàn)橘x值重載一定是針對(duì)于已經(jīng)創(chuàng)建過的對(duì)象,我們將構(gòu)造函數(shù)和拷貝構(gòu)造禁掉就避免了棧對(duì)象的出現(xiàn),被創(chuàng)建的一定是堆上的,那么堆上的對(duì)象賦值還是在堆上。

當(dāng)然我們還有第二種只在堆上創(chuàng)建的類的思想:

class HeapOnly
{
public:
	HeapOnly()
	{}
	void Destroy()
	{
		this->~HeapOnly();
	}
private:
	~HeapOnly()
	{}
	HeapOnly(const HeapOnly&) = delete;
};

我們將析構(gòu)函數(shù)設(shè)為私有,這樣只要是棧上創(chuàng)建的對(duì)象都會(huì)編譯報(bào)錯(cuò),因?yàn)闊o法調(diào)用其析構(gòu)函數(shù),但是指針卻可以正常的開辟空間,當(dāng)我們將析構(gòu)函數(shù)設(shè)為私有后那么該如何釋放空間呢?只需要加一個(gè)成員函數(shù),讓這個(gè)成員函數(shù)調(diào)用類內(nèi)的析構(gòu)就可以了,這里不能直接調(diào)用析構(gòu)需要用this指針指向一下否則會(huì)有編譯錯(cuò)誤。

 可以看到是沒有問題的。

下面我們實(shí)現(xiàn)只在棧上創(chuàng)建的類:

只在棧上創(chuàng)建我們只需要禁掉operator new和operator delete以及禁止static變量即可。

class StackOnly
{
public:
	static StackOnly CreatObj()
	{
		return StackOnly();
	}
	void print()
	{
		cout << "print()" << endl;
	}
private:
	StackOnly()
	{}
};

一旦我們將構(gòu)造函數(shù)禁掉,那么static變量和stackOnly* = new都無法創(chuàng)建。當(dāng)然這個(gè)類是封不死的對(duì)于下面這個(gè)情況:

static StackOnly st = StackOnly::CreatObj();

這也是這個(gè)類的缺陷,當(dāng)然我們也可以直接禁掉operator new ,但是沒必要因?yàn)槲覀兘粑鰳?gòu)后就無法調(diào)用new,畢竟new是需要構(gòu)造函數(shù)的。

二、單例模式

設(shè)計(jì)模式:

設(shè)計(jì)模式( Design Pattern )是一套 被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類的、代碼設(shè)計(jì)經(jīng)驗(yàn)的 總結(jié) 。

為什么會(huì)產(chǎn)生設(shè)計(jì)模式這樣的東西呢?就像人類歷史發(fā)展會(huì)產(chǎn)生兵法。最開始部落之間打 仗時(shí)都是人拼人的對(duì)砍。后來春秋戰(zhàn)國時(shí)期,七國之間經(jīng)常打仗,就發(fā)現(xiàn)打仗也是有 套路 的,后 來孫子就總結(jié)出了《孫子兵法》。孫子兵法也是類似。

使用設(shè)計(jì)模式的目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。 設(shè)計(jì)模 式使代碼編寫真正工程化;設(shè)計(jì)模式是軟件工程的基石脈絡(luò),如同大廈的結(jié)構(gòu)一樣。

單例模式: 一個(gè)類只能創(chuàng)建一個(gè)對(duì)象,即單例模式,該模式可以保證系統(tǒng)中該類只有一個(gè)實(shí)例,并提供一個(gè) 訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享 。比如在某個(gè)服務(wù)器程序中,該服務(wù)器的配置 信息存放在一個(gè)文件中,這些配置數(shù)據(jù)由一個(gè)單例對(duì)象統(tǒng)一讀取,然后服務(wù)進(jìn)程中的其他對(duì)象再 通過這個(gè)單例對(duì)象獲取這些配置信息,這種方式簡化了在復(fù)雜環(huán)境下的配置管理。

1.餓漢模式

我們先寫出代碼然后進(jìn)行講解:

#include <map>
class InfoSingleton
{
public:
	static InfoSingleton& GetInstance()
	{
		return _sin;
	}
	void insert(string name,int salary)
	{
		_info[name] = salary;
	}
	void print()
	{
		for (auto& e : _info)
		{
			cout << e.first << " : " << e.second << endl;
		}
		cout << endl;
	}
private:
	InfoSingleton()
	{}
	InfoSingleton(const InfoSingleton&) = delete;
	InfoSingleton& operator=(const InfoSingleton&) = delete;
	map<string, int> _info;
	static InfoSingleton _sin;
};

首先單例模式是只能創(chuàng)建一個(gè)對(duì)象,所以我們必須將構(gòu)造函數(shù)設(shè)為私有,上面的場景是一個(gè)工資管理表用map存放,既然只有一個(gè)類我們就直接加了一個(gè)私有靜態(tài)成員,這個(gè)成員就是我們唯一使用的類,注意我們還需要將這個(gè)靜態(tài)成員在類外初始化:

InfoSingleton InfoSingleton::_sin;

然后我們?cè)O(shè)計(jì)一個(gè)getinstance的接口可以返回這個(gè)私有對(duì)象,注意返回的是引用因?yàn)橹挥幸粋€(gè)類不能產(chǎn)生拷貝。insert和print接口是為了演示所以設(shè)計(jì)出來了,然后我們要將拷貝構(gòu)造和賦值都禁掉,還是那個(gè)原因只有一個(gè)對(duì)象。接下來我們運(yùn)行起來看看:

int main()
{
	InfoSingleton::GetInstance().insert("張三", 20);
	InfoSingleton& sl = InfoSingleton::GetInstance();
	sl.insert("李四", 200);
	sl.insert("王五", 600);
	sl.insert("趙六", 3100);
	sl.print();
	return 0;
}

上面的代碼中我們給出了兩種拿到這個(gè)類的唯一對(duì)象的方法,一種是利用靜態(tài)成員函數(shù)的特性直接使用,另一個(gè)是引用接收,下面我們看看結(jié)果:

 結(jié)果也是沒有問題的,下面我們說一說餓漢模式的缺點(diǎn):

首先因?yàn)殪o態(tài)成員變量的原因,我們的類會(huì)在main函數(shù)開始之前就創(chuàng)建對(duì)象,這么做就會(huì)有一些缺點(diǎn),比如:單例對(duì)象初始化的時(shí)候數(shù)據(jù)太多,會(huì)導(dǎo)致啟動(dòng)慢。2.多個(gè)單例類如果有初始化依賴關(guān)系的話,那么餓漢模式是無法保證哪個(gè)類先初始化的(比如:A和B都是單例類,我們要求B先初始化然后再初始化A,但是餓漢模式是無法控制順序的)。

2.懶漢模式

懶漢模式和餓漢模式的區(qū)別在于,懶漢模式是等需要用到對(duì)象的時(shí)候再創(chuàng)建,下面我們寫一下代碼:

class InfoSingleton
{
public:
	static InfoSingleton* GetInstance()
	{
		//第一次獲取單例對(duì)象的時(shí)候創(chuàng)建對(duì)象
		if (_psin == nullptr)
		{
			return new InfoSingleton;
		}
		return _psin;
	}
	void insert(string name, int salary)
	{
		_info[name] = salary;
	}
	void print()
	{
		for (auto& e : _info)
		{
			cout << e.first << " : " << e.second << endl;
		}
		cout << endl;
	}
private:
	InfoSingleton()
	{}
	InfoSingleton(const InfoSingleton&) = delete;
	InfoSingleton& operator=(const InfoSingleton&) = delete;
	map<string, int> _info;
	static InfoSingleton* _psin;
};
InfoSingleton* InfoSingleton::_psin = nullptr;

我們可以看到餓漢模式和懶漢模式代碼上的區(qū)別是:

餓漢模式用的是靜態(tài)成員變量,懶漢模式用的靜態(tài)成員變量指針,并且懶漢模式只有第一次獲取單列對(duì)象的時(shí)候才創(chuàng)建對(duì)象,這就解決了剛剛餓漢模式啟動(dòng)的時(shí)候初始化數(shù)據(jù)太多導(dǎo)致啟動(dòng)慢的問題,并且懶漢模式如果在有依賴關(guān)系的情況下是可以控制先初始化某個(gè)類再初始化某個(gè)類的。

不知道大家有沒有發(fā)現(xiàn),我們現(xiàn)在寫的懶漢模式是有一個(gè)很明顯的問題的,那就是如果是多線程的情況下第一次獲取單例對(duì)象的時(shí)候有可能多new了對(duì)象,面對(duì)這個(gè)情況我們可以直接加鎖解決問題。

//懶漢模式
class InfoSingleton
{
public:
	static InfoSingleton* GetInstance()
	{
		//第一次獲取單例對(duì)象的時(shí)候創(chuàng)建對(duì)象
		//lock_guard<mutex> lock(_mtx);
		if (_psin == nullptr)
		{
			lock_guard<mutex> lock(_mtx);
			if (_psin == nullptr)
			{
				return new InfoSingleton;
			}
		}
		return _psin;
	}
private:
	InfoSingleton()
	{}
	InfoSingleton(const InfoSingleton&) = delete;
	InfoSingleton& operator=(const InfoSingleton&) = delete;
	map<string, int> _info;
	static InfoSingleton* _psin;
	static mutex _mtx;
};
InfoSingleton* InfoSingleton::_psin = nullptr;
mutex InfoSingleton::_mtx;

首先我們定義鎖的時(shí)候必須是靜態(tài)的,這是因?yàn)間etinstance這個(gè)函數(shù)就是靜態(tài)的,這個(gè)函數(shù)里是無法調(diào)用普通成員函數(shù)的,只能調(diào)用靜態(tài)成員函數(shù),并且我們的鎖只需要保護(hù)第一次來判斷是否需要?jiǎng)?chuàng)建對(duì)象的情況,如果寫成下面這樣的代碼就會(huì)造成資源浪費(fèi):

static InfoSingleton* GetInstance()
	{
			lock_guard<mutex> lock(_mtx);
			if (_psin == nullptr)
			{
				return new InfoSingleton;
			}
		return _psin;
	}

為什么會(huì)造成資源浪費(fèi)呢?因?yàn)榈谝淮蝿?chuàng)建后后面的幾次我們只需要返回這個(gè)對(duì)象的指針,這個(gè)時(shí)候是不需要加鎖的,而像上面的代碼我們即使已經(jīng)創(chuàng)建過一次對(duì)象了進(jìn)來后還是要加鎖解鎖消耗資源,這就造成了資源的浪費(fèi),所以我們多做一個(gè)判斷就能解決這個(gè)問題。注意:餓漢模式是沒有這個(gè)線程安全的問題的,因?yàn)轲I漢模式在main函數(shù)之前就創(chuàng)建好對(duì)象了,main函數(shù)之前是不會(huì)有兩個(gè)線程去創(chuàng)建對(duì)象的。

當(dāng)然一般情況下我們的單例對(duì)象是不考慮釋放的,不過如果需要釋放該如何釋放呢?其實(shí)和創(chuàng)建的時(shí)候一樣,寫一個(gè)靜態(tài)的接口即可,代碼如下:

static void DelInstance()
	{
		lock_guard<mutex> lock(_mtx);
		if (_psin != nullptr)
		{
			delete _psin;
			_psin = nullptr;
		}
	}

當(dāng)然也有人想到如果有些人就是忘記手動(dòng)釋放資源那就麻煩了,所以又出現(xiàn)了一個(gè)自動(dòng)的釋放資源的方法:

class GC
	{
	public:
		~GC()
		{
			if (_psin)
			{
				cout << "~GC()" << endl;
				DelInstance();
			}
		}
	};

GC是這個(gè)類對(duì)象的內(nèi)部類,這個(gè)類的析構(gòu)函數(shù)就是如果我們沒有手動(dòng)釋放單例類的資源,那么GC這個(gè)對(duì)象出了作用域會(huì)自動(dòng)幫我們進(jìn)行銷毀。

 下面我們將程序運(yùn)行起來看看能否釋放:

 上面是我們自己手動(dòng)釋放后,GC就沒有幫我們釋放,下面我們?cè)倏纯醋约翰皇謩?dòng)釋放GC是否會(huì)幫我們釋放:

 所以我們總結(jié)一下,GC有下面兩個(gè)好處:

可以手動(dòng)調(diào)用主動(dòng)回收,也可以讓它在程序結(jié)束時(shí)自動(dòng)回收。

當(dāng)然下面還有一種更簡單的懶漢模式的實(shí)現(xiàn)方法:

class InfoSingleton
{
public:
	static InfoSingleton& GetInstance()
	{
		static InfoSingleton sin;
		return sin;
	}
	void insert(string name, int salary)
	{
		_info[name] = salary;
	}
	void print()
	{
		for (auto& e : _info)
		{
			cout << e.first << " : " << e.second << endl;
		}
		cout << endl;
	}
private:
	InfoSingleton()
	{}
	InfoSingleton(const InfoSingleton&) = delete;
	InfoSingleton& operator=(const InfoSingleton&) = delete;
	map<string, int> _info;
};

為什么這種方法也被稱為懶漢模式呢?這是因?yàn)間etinstance這個(gè)函數(shù)內(nèi)部定義的靜態(tài)變量sin是一個(gè)局部靜態(tài)變量,一個(gè)局部的靜態(tài)成員變量在初始化的時(shí)候是在main函數(shù)后初始化,所以和我們new的效果一樣,并且還不用加鎖保護(hù)。這個(gè)方式就利用了一個(gè)知識(shí)點(diǎn):靜態(tài)的局部變量是在main函數(shù)之后才創(chuàng)建初始化的。但是對(duì)于這樣的寫法有一個(gè)點(diǎn)需要注意:

 在C++11之前,上面紅框的部分是不能保證sin的初始化是線程安全的,在C++11之后,可以保證sin的初始化是線程安全的。

總結(jié)

設(shè)計(jì)模式中最重要的就是單例模式了,這個(gè)模式在面試中是高頻考點(diǎn)大家一定要學(xué)會(huì)。

到此這篇關(guān)于C++定制刪除器與特殊類設(shè)計(jì)(餓漢和懶漢)的文章就介紹到這了,更多相關(guān)C++定制刪除器與特殊類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++超詳細(xì)實(shí)現(xiàn)堆和堆排序過像

    C++超詳細(xì)實(shí)現(xiàn)堆和堆排序過像

    堆是計(jì)算機(jī)科學(xué)中一類特殊的數(shù)據(jù)結(jié)構(gòu)的統(tǒng)稱,通常是一個(gè)可以被看做一棵完全二叉樹的數(shù)組對(duì)象。而堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。本文將通過圖片詳細(xì)介紹堆排序,需要的可以參考一下
    2022-06-06
  • C++11 上下文關(guān)鍵字的具體實(shí)踐

    C++11 上下文關(guān)鍵字的具體實(shí)踐

    本文主要介紹了C++11 上下文關(guān)鍵字的具體實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • C++?Cartographer的入口node main詳細(xì)講解

    C++?Cartographer的入口node main詳細(xì)講解

    這篇文章主要介紹了C++Node類Cartographer的入口node main,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-03-03
  • Matlab實(shí)現(xiàn)黑洞優(yōu)化算法的示例代碼

    Matlab實(shí)現(xiàn)黑洞優(yōu)化算法的示例代碼

    根據(jù)黑洞現(xiàn)象原理首次提出BH 算法,它在傳統(tǒng)PSO基礎(chǔ)上引入了新的機(jī)制,有效地提高了收斂速度并防止了陷入局部極值的情況發(fā)生.本文將用Matlab實(shí)現(xiàn)這一算法,需要的可以參考一下
    2022-06-06
  • C++使用extern實(shí)現(xiàn)源文件變量與類成員函數(shù)的巧妙共享

    C++使用extern實(shí)現(xiàn)源文件變量與類成員函數(shù)的巧妙共享

    C++中使用extern關(guān)鍵字可實(shí)現(xiàn)在源文件之間共享變量與類成員函數(shù),通過聲明變量或類在頭文件中,再在一個(gè)源文件中定義,其他源文件通過extern引用,促使模塊化、可維護(hù)的代碼組織,這篇文章主要介紹了C++用extern實(shí)現(xiàn)源文件變量與類成員函數(shù)的巧妙共享,需要的朋友可以參考下
    2024-03-03
  • Qt中const?QString轉(zhuǎn)換?char?*可能的坑

    Qt中const?QString轉(zhuǎn)換?char?*可能的坑

    本文主要介紹了Qt中const?QString轉(zhuǎn)換?char?*可能的坑,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 字符串的模式匹配詳解--BF算法與KMP算法

    字符串的模式匹配詳解--BF算法與KMP算法

    這篇文章記錄一下串里面的模式匹配,模式匹配,顧名思義就是給定一個(gè)被匹配的字符串,然后用一個(gè)字符串模式(模型)去匹配上面說的字符串,看后者是否在前者里面出現(xiàn)。常用的有2種算法可以實(shí)現(xiàn),下面我們來具體探討下
    2014-08-08
  • C語言中用于修改文件的存取時(shí)間的函數(shù)使用

    C語言中用于修改文件的存取時(shí)間的函數(shù)使用

    這篇文章主要介紹了C語言中用于修改文件的存取時(shí)間的函數(shù)使用,分別為utime()函數(shù)和utimes()函數(shù)的使用,需要的朋友可以參考下
    2015-09-09
  • C語言實(shí)例真題講解數(shù)據(jù)結(jié)構(gòu)中單向環(huán)形鏈表

    C語言實(shí)例真題講解數(shù)據(jù)結(jié)構(gòu)中單向環(huán)形鏈表

    鏈表可以說是一種最為基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)了,而單向鏈表更是基礎(chǔ)中的基礎(chǔ)。鏈表是由一組元素以特定的順序組合或鏈接在一起的,不同元素之間在邏輯上相鄰,但是在物理上并不一定相鄰。在維護(hù)一組數(shù)據(jù)集合時(shí),就可以使用鏈表,這一點(diǎn)和數(shù)組很相似
    2022-04-04
  • 基于C語言的開源csv解析庫MiniCSV的使用示例

    基于C語言的開源csv解析庫MiniCSV的使用示例

    這篇文章主要為大家詳細(xì)介紹了基于C語言中的開源csv解析庫——MiniCSV的使用示例,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-07-07

最新評(píng)論

光泽县| 阿城市| 新乡县| 浮梁县| 通化县| 桂林市| 铜山县| 荔浦县| 武山县| 盘锦市| 赤水市| 宣化县| 沂源县| 涪陵区| 牟定县| 曲周县| 繁峙县| 黎川县| 海阳市| 社旗县| 文昌市| 忻州市| 凌海市| 芮城县| 巩留县| 白银市| 宝鸡市| 眉山市| 蒙阴县| 凤庆县| 黄大仙区| 胶南市| 休宁县| 沛县| 绥芬河市| 鞍山市| 同德县| 宝坻区| 磴口县| 姚安县| 哈尔滨市|