Почему string:: compare возвращает int?

Почему string::compare возвращает int вместо меньшего типа, например short или char? Я понимаю, что этот метод возвращает только -1, 0 или 1.

Вторая часть, если бы я должен был создать метод сравнения, который сравнивает два объекта типа Foo, и я хотел только вернуть -1, 0 или 1, использовать short или char, как правило, хорошая идея

EDIT: я исправлен, string::compare не возвращает -1, 0 или 1, он фактически возвращает значение > 0, < 0 или 0. Спасибо, что поддержали меня в очереди.

Похоже, что ответ грубо говоря, нет причин возвращать тип, меньший, чем int, потому что возвращаемые значения являются значениями "rvalues", а "rvalues" не имеют меньшего размера, чем тип int (4 байта). Кроме того, многие люди отметили, что регистры большинства систем, вероятно, будут иметь размер int в любом случае, поскольку эти регистры будут заполнены, если вы дадите им 1, 2 или 4 байта, нет реального преимущества для возвращения меньшее значение.

РЕДАКТИРОВАТЬ 2: на самом деле, похоже, что при использовании меньших типов данных, таких как выравнивание, маскировка и т.д. могут быть дополнительные накладные расходы. Общий консенсус в том, что существуют меньшие типы данных для сохранения памяти при работе с большим количеством данных, как в случае массива.

Узнал что-то сегодня, еще раз спасибо ребятам!

Ответ 1

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

В С++ (как в C) каждое выражение представляет собой либо r-значение, либо именующий. Исторически термины ссылаются на то, что lvalues появляются слева от задания, где, поскольку значения могут быть только появляются справа. Сегодня простое приближение для типы non-class - это то, что lvalue имеет адрес в памяти, rvalue - нет. Таким образом, вы не можете взять адрес rvalue, и cv-квалификаторы (условие "доступ" ) не применяются. В C++ термины, rvalue, который не имеет типа класса, является чистым значение, а не объект. Возвращаемое значение функции является rvalue, если только он не имеет ссылочного типа. (Типы неклассов, которые поместиться в регистр почти всегда будет возвращен в регистр, например, а не в памяти.)

Для типов классов проблемы немного сложнее из-за факт, что вы можете вызвать функции-члены на r-значении. Эта означает, что rvalues ​​должны иметь адреса, для this указатель, и может быть квалифицированным, поскольку cv-квалификация играет роль в разрешении перегрузки. Наконец, С++ 11 вводит несколько новых различий, чтобы поддерживать ссылки rvalue; они также в основном применимы к типам классов.

Интегральное продвижение означает тот факт, что когда интегральные типы меньше, чем int, используются как значения r в выражении, в большинство контекстов, они будут продвигаться до int. Так что даже если У меня есть переменная, объявленная short a, b;, в выражении a + b, и a, и b продвигаются до int перед добавлением имеет место. Аналогично, если я пишу a < 0, сравнение выполняется на значение a, преобразованное в int. На практике очень немногие случаи, когда это имеет значение, по крайней мере, на 2 дополняет машины, где целые арифметические обертывания (т. все, кроме очень немногих экзотических, сегодня, я думаю, Unisys мэйнфреймы - единственные исключения). Тем не менее, даже на более распространенные машины:

short a = 1;
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( a + 0 ) << std::endl;

должны давать разные результаты: первый - это эквивалент sizeof( short ), второй sizeof( int ) (из-за интегральное продвижение).

Эти два вопроса формально ортогональны; rvalues ​​и lvalues не имеют ничего общего с цельной рекламой. Кроме... интегральное продвижение распространяется только на rvalues, и большинство (но не все) случаев, когда вы используете rvalue, приведет к интегральное продвижение. По этой причине действительно нет причин для возврата числового значения в чем-то меньшем, чем int. Существует даже очень хорошая причина не возвращать его, как тип символа. Перегруженные операторы, такие как <<, часто ведут себя по-разному для типов символов, поэтому вы хотите только вернуться символы как типы символов. (Вы можете сравнить разница:

char f() { return 'a'; }
std::cout << f() << std::endl;      //  displays "a"
std::cout << f() + 0 << std::endl;  //  displays "97" on my machine

Различие заключается в том, что во втором случае добавление имеет вызванное целым поощрением, что приводит к перегрузка <<.

Ответ 2

Преднамеренно, что он не возвращает -1, 0 или 1.

Это позволяет (обратите внимание, что это не для строк, но в равной степени относится к строкам)

int compare(int *a, int *b)
{
   return *a - *b;
}

что намного менее громоздко, чем:

int compare(int *a, int *b)
{
   if (*a == *b) return 0;
   if (*a > *b) return 1;
   return -1;
}

что вам нужно сделать [или что-то в этом роде], если вам нужно вернуть -1, 0 или 1.

И он работает и для более сложных типов:

class Date
{
    int year;
    int month;
    int day;
}

int compare(const Date &a, const Date &b)
{
   if (a.year != b.year) return a.year - b.year;
   if (a.month != b.month) return a.month - b.month;
   return a.day - b.day;
}

В строковом случае мы можем сделать это:

int compare(const std::string& a, const std::string& b)
{
   int len = min(a.length(), b.length());

   for(int i = 0; i < len; i++)
   {
      if (a[i] != b[i]) return a[i] - b[i];
   }
   // We only get here if the string is equal all the way to one of them
   // ends. If the length isn't equal, "longest" wins. 
   return a.length() - b.length();
}

Ответ 3

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

Меньшие типы существуют, главным образом, для оптимизации использования ОЗУ для массивов и структур. В большинстве случаев они используют несколько циклов процессора (в виде операций с псевдонимом) для лучшего использования ОЗУ.

Если вам не нужно принудительно использовать возвращаемое значение как подписанное или неподписанное число сантинуального размера (char, short...), вам лучше использовать int, поэтому стандартная библиотека делает это.

Ответ 4

Это C-ism.

Когда C требует функции compare -type, они всегда возвращают int. С++ просто переносил это вперед (к сожалению).

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

Ответ 5

Метод фактически не возвращает целое число в наборе { -1, 0, 1 }; это может быть любое целое значение.

Почему? Основная причина, по которой я могу думать, заключается в том, что int должен быть значением "естественного размера" для архитектуры; операции с значениями этого размера обычно не менее быстры (и во многих случаях быстрее), чем операции с меньшими или большими значениями. Таким образом, это случай, позволяющий реализации достаточно слабого использовать то, что быстрее.

Ответ 6

если бы я должен был создать метод сравнения, который сравнивает два объекта типа Foo, и я хотел бы только вернуть -1, 0 или 1, то использование коротких или char вообще было бы хорошей идеей?

Это было бы хорошо. Лучшим способом было бы вернуть bool (если хотите сравнить только если он равен) или перечисление (для получения дополнительной информации):

enum class MyResult
{
  EQUAL,
  LESS,
  GREATER
};

MyResult AreEqual( const Foo &foo1, const Foo & foo2 )
{
  // calculate and return result
}

Ответ 7

Предположим, что некоторые люди меняют код с C на С++. Они решили заменить strcmp на string::compare.

Так как strcmp возвращает int, проще string::compare вернуть int в качестве подарка.

Ответ 8

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

Кроме того, возвращаемое значение не просто -1, 0 или 1, но <0, 0 или >0.

Кроме того, как было упомянуто, поскольку возврат подпадает под интегральное продвижение, нет смысла уменьшать его.

Ответ 9

поскольку логическое возвращаемое значение может быть только двумя возможными значениями (true, false), а функция сравнения может возвращать три возможных значения (меньше, равно, больше).

Обновление

Несмотря на то, что, возможно, можно вернуть подписанный короткий код, если вы действительно хотите реализовать свою собственную функцию сравнения, вы можете вернуть значение nibble или struct с двумя логическими значениями.