Pourquoi #include empêche-t-il une erreur de débordement de stack ici?

Ceci est mon exemple de code:

#include  #include  using namespace std; class MyClass { ssortingng figName; public: MyClass(const ssortingng& s) { figName = s; } const ssortingng& 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; } 

Si je commente #include je ne reçois aucune erreur du compilateur, je suppose parce que c’est inclus par le biais de #include . Si je clique avec le bouton droit sur Aller à la définition dans Microsoft VS, ils pointent tous deux vers la même ligne dans le fichier xssortingng :

 typedef basic_ssortingng<char, char_traits, allocator > ssortingng; 

Mais quand je lance mon programme, je reçois une erreur d’exception:

0x77846B6E (ntdll.dll) dans OperatorSsortingng.exe: 0xC00000FD: débordement de stack (paramètre: 0x00000001, 0x01202FC4)

Toute idée de la raison pour laquelle je reçois une erreur d’exécution lors du commentaire #include ? J’utilise VS 2013 Express.

En effet, comportement très intéressant.

Toute idée de la raison pour laquelle je reçois une erreur d’exécution lors du commentaire #include

Avec MS VC ++ comstackr, l’erreur se produit car si vous n’incluez pas #include vous n’aurez pas d’ operator<< défini pour std::ssortingng .

Lorsque le compilateur essaie de comstackr ausgabe << f.getName(); il recherche un operator<< défini pour std::ssortingng . Comme il n'a pas été défini, le compilateur recherche des alternatives. Il y a un operator<< défini pour MyClass et le compilateur essaie de l'utiliser, et pour l'utiliser, il doit convertir std::ssortingng en MyClass et c'est exactement ce qui se passe car MyClass a un constructeur non explicite! Ainsi, le compilateur finit par créer une nouvelle instance de MyClass et essaie de le diffuser à nouveau dans votre stream de sortie. Cela se traduit par une récursion sans fin:

  start: operator<<(MyClass) -> MyClass::MyClass(MyClass::getName()) -> operator<<(MyClass) -> ... goto start; 

Pour éviter l'erreur, vous devez #include pour vous assurer qu'il existe un operator<< défini pour std::ssortingng . Vous devez également rendre votre constructeur MyClass explicite pour éviter ce genre de conversion inattendue. Règle de sagesse: rendre les constructeurs explicites s'ils ne prennent qu'un seul argument pour éviter la conversion implicite:

 class MyClass { ssortingng figName; public: explicit MyClass(const ssortingng& s) // <<-- avoid implicit conversion { figName = s; } const string& getName() const { return figName; } }; 

Il semble que operator<< for std::ssortingng soit défini uniquement lorsque est inclus (avec le compilateur MS) et pour cette raison, tout se comstack, mais vous obtenez un comportement inattendu car operator<< est appelé de manière récursive à la place de MyClass de l' operator<< appel operator<< for std::ssortingng .

Cela signifie-t-il que la chaîne #include n'est incluse qu'en partie?

Non, la chaîne est entièrement incluse, sinon vous ne pourriez pas l'utiliser.

Le problème est que votre code effectue une récursion infinie. L’opérateur de streaming pour std::ssortingng ( std::ostream& operator<<(std::ostream&, const std::string&) ) est déclaré dans le fichier d'en-tête , bien que std::ssortingng soit déclaré dans un autre fichier d'en-tête (inclus à la fois par et ).

Lorsque vous n'incluez pas le compilateur essaie de trouver un moyen de comstackr ausgabe << f.getName(); .

Il arrive que vous ayez défini à la fois un opérateur de diffusion en continu pour MyClass et un constructeur qui admet une std::ssortingng , de sorte que le compilateur l'utilise (via une construction implicite ), créant un appel récursif.

Si vous déclarez explicit votre constructeur ( explicit MyClass(const std::ssortingng& s) ) alors votre code ne sera plus compilé, puisqu'il n'y a aucun moyen d'appeler l'opérateur streaming avec std::ssortingng , et vous serez obligé de inclure l'en-tête .

MODIFIER

Mon environnement de test est VS 2010, et à partir du niveau 1 ( /W1 ), il vous avertit du problème:

warning C4717: 'operator <<': récursif sur tous les chemins de contrôle, la fonction provoquera un débordement de pile d'exécution