下面的 C++ 代码在 Visual Studio 2008 中生成以下警告:
1>c:...\sample.cpp(6) : 警告 C4717: 'operator<' : 在所有控制路径上递归,函数将 > 导致运行时堆栈溢出
如果我在需要 operator< 的任何情况下使用 Sample 类,它实际上会因堆栈溢出错误而崩溃(例如,在将第二个 Sample 对象插入到多重集中之后)。构造函数一直被调用,直到堆栈空间用完。
下面的代码是自行生成警告所需的全部内容(代码中没有任何引用 Sample 类的内容)。
// Sample.hpp
#include <iostream>
class __declspec(dllexport) Sample
{
std::string ID;
public:
Sample (std::string id):ID(id) {};
friend bool __declspec(dllexport) operator<(const Sample& s1, const Sample& s2);
};
// Sample.cpp
#include "Sample.hpp"
bool operator<(const Sample& s1, const Sample& s2)
{
return s1.ID<s2.ID;
}
在 Win7 上使用 VC++ 和 VS2008 (Win32, /W3) 显示警告。对于相同的平台和完全相同的代码,但在 Eclipse 上使用 MinGW GCC 4.7.3,我没有收到任何警告。
如果我添加 < string > 标题,则警告在 VS2008 中消失,并且 Sample 类的任何使用都可以正常工作。
此外,如果我显式声明 Sample 构造函数,VS2008 会引发以下编译错误:
1>.\Sample.cpp(5) : error C2678: binary '<' : no operator found which takes a left-hand operand of > type 'const std::string' (或没有可接受的转换) 1> c :...\Sample.hpp(13): 可能是 'bool operator <(const Sample &,const Sample &)' 1> 尝试匹配参数列表 '(const std::string, const std::string )'
但是,在 GCC 中显式设置构造函数仍然不会产生任何警告或错误(我将 Eclipse 中的警告设置为我能做到的最全面的级别)。
我想知道是否有人可以大致解释一下VS2008如何确定何时生成此堆栈溢出警告。在这种情况下,事实证明它是正确的,所以我很想知道它是如何完成的。另外,如果可能的话,为什么 GCC 在这里表现不同。希望这是有道理的。