Это слишком умно или небезопасно?

Оператор == проверяет, указывают ли две ссылки на один и тот же объект или нет. .equals() проверьте фактическое содержимое строки (значение).

Обратите внимание, что метод .equals() принадлежит классу Object (суперкласс всех классов). Вам необходимо переопределить его в соответствии с вашим требованием к классу, но для String оно уже реализовано и проверяет, имеет ли две строки одно и то же значение.

  • Случай 1
    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true
    
    Причина: строка литералы, созданные без нуля, хранятся в пуле строк в области перментонов кучи. Таким образом, оба s1 и s2 указывают на один и тот же объект в пуле.
  • Случай 2
    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true
    
    Причина. Если вы создаете объект String с использованием ключевого слова new, ему выделяется отдельное пространство в куче.
13
задан alain.janinm 29 April 2012 в 16:44
поделиться

8 ответов

Насколько я могу судить, это безопасно, но для всех нужно искать дважды чтение кода. Зачем вам это нужно?

В любом случае, для сравнения, все, что вам когда-либо понадобится, это < и либо == , либо ! = , остальное канонично, и я пишу его в основном мышечная память.Кроме того, бинарные операторы, которые одинаково обрабатывают свои операнды (оставляют их в покое), должны быть реализованы как не члены 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 <.

8
ответ дан 1 December 2019 в 17:37
поделиться

Умно?

предупреждение: см. Комментарии

Я думаю, что для ! = неэффективно вызывать compare (который проверяет все значения обеих матриц, чтобы узнать, какой из них больше), потому что если m1 [0] [0]! = m2 [0] [0] , то ! = уже может вернуть false . Поэтому я думаю, что было бы неплохо упростить написание этих операторов, и если производительность вообще не имеет значения, это можно считать умным. Но если производительность имеет значение , это не умно.

Безопасно?

Я также считаю, что это безопасно, потому что дает правильные результаты.

2
ответ дан 1 December 2019 в 17:37
поделиться

Как упоминалось ранее, я думаю, что стандартным способом было бы вернуть < 0, когда LHS < RHS, > 0 для LHS > RHS и 0 для равенства.

Но могу ли я задать другой вопрос? Зачем вообще использовать здесь перегрузку оператора? Идея перегрузки оператора заключается (или должна быть) в том, чтобы иметь возможность использовать объекты интуитивным образом. Но, насколько мне известно, не существует стандартного определения для сравнения матриц, кроме (не)равенства. По крайней мере, я не знаю ни одного. Итак, о чем я должен думать, когда читаю M1 < M2?

Просто позвольте мне догадаться: оператор<() и оператор>() были только что добавлены для полноты, но никогда не будут использоваться в реальном коде - верно? Если это так, не реализуйте их.

2
ответ дан 1 December 2019 в 17:37
поделиться

Да, это слишком умно - я прочитал этот код и должен подумать, почему вы вычитаете два из функции с именем compare . Не заставляй меня думать.

Если вы сообразили, что код умещается в одну строку, то у вас спутанные приоритеты. Вы должны использовать столько строк, сколько необходимо, чтобы сделать ваш код максимально понятным.

Программы должны быть написаны для того, чтобы их могли читать люди, и только в случае необходимости для выполнения машинами. (Абельсон и Сассман, Структура и интерпретация компьютерных программ)

22
ответ дан 1 December 2019 в 17:37
поделиться

Да, это слишком сложно.

compare должен возвращать 0 для равных значений, положительный, если this больше, и отрицательный, если this меньше.

Это было бы намного проще и было бы даже с одинаковой производительностью.

Если бы я дал этот код на проверку, я бы отметил, что это необходимо исправить.

8
ответ дан 1 December 2019 в 17:37
поделиться

Сравнение результата 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;
}
5
ответ дан 1 December 2019 в 17:37
поделиться

Я подскажу вам свой путь:

#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 , которые могут иметь дело только с матрицами аналогичных размеров, поскольку все остальное является ересью, и, следовательно, иметь диагностику во время компиляции.

1
ответ дан 1 December 2019 в 17:37
поделиться

Если вы беспокоитесь о том, что что-то слишком умно ... вероятно, это: -)

3
ответ дан 1 December 2019 в 17:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: