STL中的swap函數的坑

最近刷LeetCode題目第30題時,自定義一個字符串數組的全排列函數時,遇到了一個坑,先看字符串數組全排列函數如下:

unordered_set<string> help;


void combine(int start, int end, vector<string>& words)
{
	if (start == end)
	{
		string res;
		int len = words.size();
		for (int  i = 0; i < len; ++i)
		{
			res += words[i];
		}
		help.insert(res);
		return;
	}
	else if (start < end)
	{
		for (int  i = start; i <= end; ++i)
		{
			/* void selfSwap(string & a, string & b){string tmp;tmp = a;a = b;b = tmp;} */
			/*selfSwap(words[start], words[i]);
			combine(start + 1, end, words);
			selfSwap(words[start], words[i]);*/

			//下面這段代碼使用標準庫提供的交換函數有問題,編譯報錯
			swap<string>(words[start], words[i]);
			combine(start + 1, end, words);
			swap<string>(words[start], words[i]);  //回溯
		}
	}
}

乍一看這代碼貌似能實現全排列,可是在VS2019下編譯都通不過,報錯如下:

換個文字版的錯誤碼,便於以後哪位遇到了同樣的坑的時候查詢:

Visual Studio\VC\Tools\MSVC\14.20.27508\include\chrono(595): note: 參見對正在編譯的 類 模板 實例化 "std::chrono::duration<double,std::ratio<1,1>>" 的引用
Visual Studio\VC\Tools\MSVC\14.20.27508\include\chrono(172): note: 參見對正在編譯的 類 模板 實例化 "std::chrono::duration<__int64,std::nano>" 的引用
Visual Studio\VC\Tools\MSVC\14.20.27508\include\chrono(574): note: 參見對正在編譯的 類 模板 實例化 "std::chrono::time_point<std::chrono::steady_clock,std::chrono::steady_clock::duration>" 的引用
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1702): error C2061: 語法錯誤: 標識符“_Alloc”
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1703): error C2065: “_Alvbase”: 未聲明的標識符
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1703): error C2923: “std::allocator_traits”: 對於參數“_Alloc”,“_Alvbase”不是有效的 模板 類型變量
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1703): error C2903: “allocator_traits”: 符號既不是類 模板 也不是函數 模板
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1703): error C2061: 語法錯誤: 標識符“size_type”
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1704): error C2065: “_Alvbase”: 未聲明的標識符
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1704): error C2923: “std::allocator_traits”: 對於參數“_Alloc”,“_Alvbase”不是有效的 模板 類型變量
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1704): error C2903: “allocator_traits”: 符號既不是類 模板 也不是函數 模板
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1704): error C2061: 語法錯誤: 標識符“difference_type”
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1705): error C2065: “_Alvbase”: 未聲明的標識符
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1705): error C2923: “std::_Rebind_alloc_t”: 對於參數“_Alloc”,“_Alvbase”不是有效的 模板 類型變量
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1705): error C2903: “vector”: 符號既不是類 模板 也不是函數 模板
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1710): error C2061: 語法錯誤: 標識符“_Sizet”
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1715): error C2061: 語法錯誤: 標識符“_Sizet”
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1721): error C2061: 語法錯誤: 標識符“_Sizet”
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1737): error C3646: “_Myoff”: 未知重寫說明符
Visual Studio\VC\Tools\MSVC\14.20.27508\include\vector(1737): error C4430: 缺少類型說明符 - 假定爲 int。注意: C++ 不支持默認 int
算法競賽代碼\牛客網刷題調試\牛客網刷題調試\串聯所有單詞的子串  --LeetCode30題.cpp(72): warning C4018: “<”: 有符號/無符號不匹配

在LeetCode上代碼是能通過編譯的,但是VS下這錯誤看得我一頭霧水,後來手動把代碼一行一行的敲進去,每加一個代碼塊便編譯一遍,最終確定了編譯錯誤是出在了標準庫中的swap函數這一段。

後來查了下STL中swap函數的坑,看了一篇博文(地址:https://blog.csdn.net/iwts_24/article/details/79487501),這位大佬原話如下:

swap函數交換的是兩個變量的地址,證據(VS中的swap函數的源碼)如下:

template <class _Ty, class>
inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&&
        is_nothrow_move_assignable_v<_Ty>) { // exchange values stored at _Left and _Right
    _Ty _Tmp = _STD move(_Left);
    _Left    = _STD move(_Right);
    _Right   = _STD move(_Tmp);
}

而對於string類型,string在調用swap後,迭代器、引用、指針都會失效。所以這段代碼會報錯,將標準庫的swap函數換成自己寫的交換函數,代碼就能通過編譯了。

unordered_set<string> help;

void selfSwap(string& a, string& b)
{
	string tmp;
	tmp = a;
	a = b;
	b = tmp;
}

void combine(int start, int end, vector<string>& words)
{
	if (start == end)
	{
		string res;
		int len = words.size();
		for (int  i = 0; i < len; ++i)
		{
			res += words[i];
		}
		help.insert(res);
		return;
	}
	else if (start < end)
	{
		for (int  i = start; i <= end; ++i)
		{
			/* void selfSwap(string & a, string & b){string tmp;tmp = a;a = b;b = tmp;} */
			selfSwap(words[start], words[i]);
			combine(start + 1, end, words);
			selfSwap(words[start], words[i]);

			//下面這段代碼使用標準庫提供的交換函數有問題,編譯報錯
			//swap<string>(words[start], words[i]);
			//combine(start + 1, end, words);
			//swap<string>(words[start], words[i]);  //回溯
		}
	}
}

參考博文連接:https://blog.csdn.net/iwts_24/article/details/79487501

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章