最近刷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