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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值