Приведенный ниже код C++ генерирует следующее предупреждение в Visual Studio 2008:
1>c:...\sample.cpp(6): предупреждение C4717: 'оператор‹': рекурсивный на всех путях управления, функция > вызовет переполнение стека во время выполнения
Если я использую класс 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;
}
Предупреждение отображается с VC++ и VS2008 (Win32, /W3) на Win7. Для той же платформы и точно такого же кода, но с MinGW GCC 4.7.3 в eclipse я не получаю никаких предупреждений.
Если я добавлю заголовок ‹ string >, предупреждение исчезнет в VS2008, и любое использование класса Sample будет работать отлично.
Кроме того, если я объявлю конструктор Sample явным, VS2008 выдаст следующую ошибку компиляции:
1>.\Sample.cpp(5): ошибка C2678: двоичный файл '‹': не найден оператор, который принимает левый операнд > типа 'const std::string' (или нет приемлемого преобразования) 1> c :...\Sample.hpp(13): может быть 'логическим оператором ‹(const Sample &,const Sample &)' 1> при попытке сопоставить список аргументов '(const std::string, const std::string )'
Однако установка явного конструктора в GCC по-прежнему не генерирует ни предупреждений, ни ошибок (я установил предупреждения в Eclipse на наиболее полные уровни, какие только мог).
Я хотел бы знать, может ли кто-нибудь примерно объяснить, как VS2008 определяет, когда генерировать это предупреждение о переполнении стека. В этом случае это оказывается правильным, поэтому мне любопытно посмотреть, как это делается. Также, если возможно, почему GCC ведет себя по-другому здесь, пожалуйста. Надеюсь, это имеет смысл.
<string>
, чтобы иметь возможность сравниватьstd::string
объекты. Не уверен, что это решает ВСЕ проблемы, но должно решить вторую. - person Mats Petersson   schedule 04.08.2013Sample
из каждой сравниваемой строки, а затем сравнивая их. Вот почему явный ctor его ломает и почему он бесконечно рекурсивен — потому что он создает новые временные объекты того же типа, что и полученные в качестве параметров, и пытается их сравнить. - person Jerry Coffin   schedule 04.08.2013