Почему компиляторы C ++ не определяют operator == и operator! =? - PullRequest
273 голосов
/ 20 октября 2008

Я большой поклонник того, чтобы компилятор делал для вас как можно больше работы. При написании простого класса компилятор может дать вам «бесплатно» следующее:

  • Конструктор по умолчанию (пустой)
  • Конструктор копирования
  • Деструктор
  • Оператор присваивания (operator=)

Но это не может дать вам никаких операторов сравнения - таких как operator== или operator!=. Например:

class foo
{
public:
    std::string str_;
    int n_;
};

foo f1;        // Works
foo f2(f1);    // Works
foo f3;
f3 = f2;       // Works

if (f3 == f2)  // Fails
{ }

if (f3 != f2)  // Fails
{ }

Есть ли для этого веская причина? Почему выполнение сравнения между членами будет проблемой? Очевидно, что если класс выделяет память, вам следует быть осторожным, но для простого класса компилятор наверняка может сделать это за вас?

Ответы [ 12 ]

1 голос
/ 04 декабря 2015

Есть ли для этого веская причина? Почему выполнение сравнения по элементам будет проблемой?

Функционально это не может быть проблемой, но с точки зрения производительности сравнение по элементам по умолчанию может оказаться более неоптимальным, чем назначение / копирование по умолчанию между членами. В отличие от порядка назначения, порядок сравнения влияет на производительность, потому что первый неравный элемент подразумевает, что остальные могут быть пропущены. Поэтому, если есть некоторые члены, которые обычно равны, вы хотите сравнить их последними, и компилятор не знает, какие члены с большей вероятностью будут равны.

Рассмотрим этот пример, где verboseDescription - длинная строка, выбранная из сравнительно небольшого набора возможных описаний погоды.

class LocalWeatherRecord {
    std::string verboseDescription;
    std::tm date;
    bool operator==(const LocalWeatherRecord& other){
        return date==other.date
            && verboseDescription==other.verboseDescription;
    // The above makes a lot more sense than
     // return verboseDescription==other.verboseDescription
     //     && date==other.date;
    // because some verboseDescriptions are liable to be same/similar
    }
}

(Конечно, компилятор будет иметь право игнорировать порядок сравнений, если он признает, что они не имеют побочных эффектов, но, вероятно, он все равно будет получать свою очередь из исходного кода, где он не имеет лучшей информации о своем владеть.)

0 голосов
/ 20 октября 2008

Согласен, для классов типа POD компилятор может сделать это за вас. Однако то, что вы можете считать простым, компилятор может ошибаться. Так что лучше позволить программисту сделать это.

Однажды у меня был случай POD, когда два поля были уникальными, поэтому сравнение никогда не считалось бы верным. Однако сравнение, которое мне было нужно, сравнивалось только с полезной нагрузкой - то, что компилятор никогда не поймет или не сможет понять самостоятельно.

Кроме того - они не долго пишут, не так ли?!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...