运算符<运算符时,Visual Studio 2008运行时堆栈溢出警告在所有路径上递归

时间:2013-08-04 00:21:33

标签: c++ visual-c++ gcc4.7

下面的C ++代码在Visual Studio 2008中生成以下警告:

  

1> c:... \ sample.cpp(6):警告C4717:'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,我没有得到任何警告。

如果我添加&lt;字符串&gt;标题警告在VS2008中消失,任何使用Sample类都可以正常工作。

此外,如果我声明Sample构造函数是显式的,VS2008会抛出以下编译错误:

  

1&gt;。\ Sample.cpp(5):错误C2678:二进制'&lt;' :找不到哪个运算符采用&gt;的左手操作数输入'const std :: string'(或者没有可接受的转换)   1 GT; c:... \ Sample.hpp(13):可能是'bool operator&lt;(const Sample&amp;,const Sample&amp;)'   1 GT;在尝试匹配参数列表'(const std :: string,const std :: string)'

但是,在GCC中显式设置构造函数仍然不会生成任何警告或错误(我将Eclipse中的警告设置为最全面的级别)。

我想知道是否有人能够大致解释VS2008如何确定何时生成此堆栈溢出警告。在这种情况下,它证明是正确的,所以我很想知道它是如何完成的。另外,如果可能的话,为什么GCC在这方面表现不同。希望这是有道理的。

1 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为在比较时std::string是一个不完整的类型,转换构造函数Sample (std::string id)正在隐式调用。在表达式s1.ID<s2.ID中,LHS和RHS都被隐式转换为临时Sample,然后再次调用转换运算符(并且一次又一次)。

您需要添加<string>,以便std::string的完整定义可见我强烈建议您声明样本explicit的构造函数。