Оператор ==
проверяет, указывают ли две ссылки на один и тот же объект или нет. .equals()
проверьте фактическое содержимое строки (значение).
Обратите внимание, что метод .equals()
принадлежит классу Object
(суперкласс всех классов). Вам необходимо переопределить его в соответствии с вашим требованием к классу, но для String оно уже реализовано и проверяет, имеет ли две строки одно и то же значение.
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s2; //true
s1.equals(s2); //true
Причина: строка литералы, созданные без нуля, хранятся в пуле строк в области перментонов кучи. Таким образом, оба s1 и s2 указывают на один и тот же объект в пуле. String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2; //false
s1.equals(s2); //true
Причина. Если вы создаете объект String с использованием ключевого слова new
, ему выделяется отдельное пространство в куче. Насколько я могу судить, это безопасно, но для всех нужно искать дважды чтение кода. Зачем вам это нужно?
В любом случае, для сравнения, все, что вам когда-либо понадобится, это <
и либо ==
, либо ! =
, остальное канонично, и я пишу его в основном мышечная память.Кроме того, бинарные операторы, которые одинаково обрабатывают свои операнды (оставляют их в покое), должны быть реализованы как не члены IMO. Учитывая это, плюс использование разумной функции сравнения ( -1
, 0
, +1
) и добавления необходимого const
, я прихожу на это:
// doing real work
inline bool operator<(const Matrix& l, const Matrix &r)
{
return -1 == compare(l,r);
}
inline bool operator==(const Matrix& l, const Matrix &r)
{
return 0 == compare(l,r);
}
// canonical
inline bool operator> (const Matrix& l, const Matrix &r) {return r < l;}
inline bool operator>=(const Matrix& l, const Matrix &r) {return !(l < r);}
inline bool operator<=(const Matrix& l, const Matrix &r) {return !(r < l);}
inline bool operator!=(const Matrix& l, const Matrix &r) {return !(l == r);}
Сравнение может быть не таким умным, как ваше, но каждый, кто когда-либо видел strcmp ()
, сразу понимает, что они делают. Обратите внимание, что я даже добавил 0! = Compare (...)
, что совершенно не нужно для компилятора. Для людей, IMO, это делает более понятным, что происходит, чем неявное приведение к bool
. Кроме того, он подчеркивает симметрию реализации operator <
.
предупреждение: см. Комментарии
Я думаю, что для ! =
неэффективно вызывать compare
(который проверяет все значения обеих матриц, чтобы узнать, какой из них больше), потому что если m1 [0] [0]! = m2 [0] [0]
, то ! =
уже может вернуть false
. Поэтому я думаю, что было бы неплохо упростить написание этих операторов, и если производительность вообще не имеет значения, это можно считать умным. Но если производительность имеет значение , это не умно.
Я также считаю, что это безопасно, потому что дает правильные результаты.
Как упоминалось ранее, я думаю, что стандартным способом было бы вернуть < 0, когда LHS < RHS, > 0 для LHS > RHS и 0 для равенства.
Но могу ли я задать другой вопрос? Зачем вообще использовать здесь перегрузку оператора? Идея перегрузки оператора заключается (или должна быть) в том, чтобы иметь возможность использовать объекты интуитивным образом. Но, насколько мне известно, не существует стандартного определения для сравнения матриц, кроме (не)равенства. По крайней мере, я не знаю ни одного. Итак, о чем я должен думать, когда читаю M1 < M2?
Просто позвольте мне догадаться: оператор<() и оператор>() были только что добавлены для полноты, но никогда не будут использоваться в реальном коде - верно? Если это так, не реализуйте их.
Да, это слишком умно - я прочитал этот код и должен подумать, почему вы вычитаете два из функции с именем compare
. Не заставляй меня думать.
Если вы сообразили, что код умещается в одну строку, то у вас спутанные приоритеты. Вы должны использовать столько строк, сколько необходимо, чтобы сделать ваш код максимально понятным.
Программы должны быть написаны для того, чтобы их могли читать люди, и только в случае необходимости для выполнения машинами. (Абельсон и Сассман, Структура и интерпретация компьютерных программ)
Да, это слишком сложно.
compare
должен возвращать 0 для равных значений, положительный, если this
больше, и отрицательный, если this
меньше.
Это было бы намного проще и было бы даже с одинаковой производительностью.
Если бы я дал этот код на проверку, я бы отметил, что это необходимо исправить.
Сравнение результата compare
с 0 с помощью любого из шести операторов сравнения даст правильный результат для соответствующего перегруженного оператора. Таким образом, ваш код будет очень читабельным, и будет сразу видно, что он правильный (если compare
реализован правильно).
inline bool Matrix::operator < (const Matrix &RHS){
return compare(*this, RHS) < 0;
}
inline bool Matrix::operator > (const Matrix &RHS){
return compare(*this, RHS) > 0;
}
inline bool Matrix::operator >= (const Matrix &RHS){
return compare(*this, RHS) >= 0;
}
inline bool Matrix::operator <= (const Matrix &RHS){
return compare(*this, RHS) <= 0;
}
inline bool Matrix::operator != (const Matrix &RHS){
return compare(*this, RHS) != 0;
}
inline bool Matrix::operator == (const Matrix &RHS){
return compare(*this, RHS) == 0;
}
Я подскажу вам свой путь:
#include <boost/operators.hpp>
class Matrix: boost::equality_comparable<Matrix
, boost::less_than_comparable<Matrix
> >
{
}; // class Matrix
bool operator==(const Matrix&, const Matrix&);
bool operator<(const Matrix&, const Matrix&);
Я использую меньше строк, чем вы, без каких-либо умных уловок. Что до Boost? Что ж, на данный момент это довольно стандартно, и это задокументировано в Интернете. Вы всегда можете добавить несколько комментариев:
// boost::equality_comparable: automatically generate != from ==
// boost::less_than_comparable: automatically generate >, <=, >= from <
// search for Boost.Operators on the web to get more information
Последнее слово: я не знаю о конкретном приложении, которое вы пишете, но, используя матрицы, я всегда считал хорошей идеей иметь базовый класс Matrix
и некоторый подкласс TMatrix
(шаблон, как указывает буква T) с размерами, известными во время компиляции. Затем вы можете предоставить операторы в TMatrix
, которые могут иметь дело только с матрицами аналогичных размеров, поскольку все остальное является ересью, и, следовательно, иметь диагностику во время компиляции.
Если вы беспокоитесь о том, что что-то слишком умно ... вероятно, это: -)