为什么#include <string>可以防止堆栈溢出错误?
这是我的示例代码:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
    string figName;
public:
    MyClass(const string& s)
    {
        figName = s;
    }
    const string& getName() const
    {
        return figName;
    }
};
ostream& operator<<(ostream& ausgabe, const MyClass& f)
{
    ausgabe << f.getName();
    return ausgabe;
}
int main()
{
    MyClass f1("Hello");
    cout << f1;
    return 0;
}
  如果我注释掉#include <string>我没有收到任何编译器错误,我猜是因为它包含在#include <iostream> 。  如果我在Microsoft VS中“右键单击 - >转到定义”,它们都指向xstring文件中的同一行: 
typedef basic_string<char, char_traits<char>, allocator<char> >
    string;
但是当我运行我的程序时,出现异常错误:
OperatorString.exe中的0x77846B6E(ntdll.dll):0xC00000FD:堆栈溢出(参数:0x00000001,0x01202FC4)
  任何想法为什么我在注释掉#include <string>时出现运行时错误?  我正在使用VS 2013 Express。 
的确,非常有趣的行为。
  任何想法为什么我在注释掉#include <string>时出现运行时错误 
  使用MS VC ++编译器时会发生错误,因为如果不包含#include <string> ,则不会为std::string定义operator<< 。 
  当编译器试图编译ausgabe << f.getName();  它寻找一个为std::string定义的operator<< 。  由于没有定义,编译器寻找替代品。  有一个operator<<为MyClass定义,并且编译器试图使用它,并且使用它必须将std::string转换为MyClass而这正是发生的原因,因为MyClass具有非显式构造函数!  因此,编译器最终会创建一个MyClass的新实例,并尝试将其再次传输到输出流。  这导致了无限的递归: 
 start:
     operator<<(MyClass) -> 
         MyClass::MyClass(MyClass::getName()) -> 
             operator<<(MyClass) -> ... goto start;
  为了避免这个错误,你需要#include <string>来确保有一个operator<<为std::string定义。  你也应该明确你的MyClass构造函数,以避免这种意外的转换。  智慧规则:如果构造函数只接受一个参数以避免隐式转换,则显式构造: 
class MyClass
{
    string figName;
public:
    explicit MyClass(const string& s) // <<-- avoid implicit conversion
    {
        figName = s;
    }
    const string& getName() const
    {
        return figName;
    }
};
  它看起来像operator<< for std::string只有在包含<string>时才会被定义(使用MS编译器),并且出于这个原因编译所有内容,但是由于operator<<正在递归调用MyClass调用operator<< for std::string 。 
  这是否意味着通过#include <iostream>字符串仅被部分包含? 
不,字符串是完全包含的,否则你将无法使用它。
  问题是您的代码正在进行无限递归。  std::string ( std::ostream& operator<<(std::ostream&, const std::string&) )的流操作符在<string>头文件中声明,尽管std::string本身在其他头文件中声明(由<iostream>和<string> )。 
  当你不包含<string> ,编译器试图找到一种方法来编译ausgabe << f.getName();  。 
  碰巧你已经定义了MyClass的流操作符和一个承认std::string的构造函数,所以编译器使用它(通过隐式构造),创建递归调用。 
  如果你声明explicit构造函数( explicit MyClass(const std::string& s)那么你的代码将不能编译了,因为没有方法来调用与流运营商std::string ,你将被迫包含<string>标题。 
编辑
  我的测试环境是VS 2010,从警告级别1( /W1 )开始,它会警告您有关此问题的信息: 
警告C4717:'operator <<':在所有控制路径上递归,函数将导致运行时堆栈溢出
链接地址: http://www.djcxy.com/p/24569.html上一篇: Why is #include <string> preventing a stack overflow error here?
