string :: compare가 int를 반환하는 이유는 무엇입니까?


102

또는 같은 더 작은 유형 대신 왜 string::compare반환 합니까? 내 이해는이 메서드는 -1, 0 또는 1 만 반환한다는 것입니다.intshortchar

두 번째 부분, 유형의 두 개체를 비교하는 비교 메서드를 디자인하고 Foo-1, 0 또는 1 만 반환하려는 경우 사용 short하거나 char일반적으로 좋은 생각일까요?

편집 : 수정되었습니다. string::compare-1, 0 또는 1을 반환하지 않습니다. 실제로 값> 0, <0 또는 0을 반환합니다.

대답은 대략적인 것 같습니다. int반환 값이 "rvalue"이고 해당 "rvalue"가 int 유형 (4 바이트)보다 작다는 이점 이 없기 때문에 보다 작은 유형을 반환 할 이유가 없습니다 . 또한 많은 사람들은 대부분의 시스템의 레지스터가 int어쨌든 크기가 될 것이라고 지적했습니다. 이 레지스터는 1, 2 또는 4 바이트 값을 제공하든 채워질 것이기 때문에 a를 반환하는 실제 이점은 없습니다. 더 작은 값.

편집 2 : 실제로 정렬, 마스킹 등과 같은 더 작은 데이터 유형을 사용할 때 추가 처리 오버 헤드가있을 수 있습니다. 일반적인 합의는 다음과 같이 많은 데이터로 작업 할 때 메모리를 절약하기 위해 더 작은 데이터 유형이 존재한다는 것입니다. 배열의 경우.

오늘 뭔가를 배웠습니다. 다시 한 번 감사드립니다!


나는 이것을 위해 사용될 수있는 더 구체적인 유형이 있다면 더 좋을 것이라고 생각한다. Ada95 스타일로 -1, 0 및 1 만 포함 된 것입니다.
Sachin Kainth 2013 년

23
string::compare()링크에 대한 문서 는 반환 값이 <0, 0 및> 0 -1, 0 및 1이
아님을 명시합니다

6
short또는 char대신 사용하는 이점은 무엇입니까 int? 대부분의 아키텍처는 레지스터에 함수의 반환 값을 저장하려고하는, 그리고는 intA와 단지뿐만 아니라 레지스터에 맞는 shortchar. 그리고 char숫자 유형에 사용 하는 것은 특히 부호있는 값이 올바르게 처리되도록 보장해야하는 경우 항상 나쁜 생각입니다.
Cody Gray

7
Obvlious 대위, 당신의 이름과 코멘트 ...
Cody Smith

2
char0보다 작은 경우 반환 값에 대한 코드 검사 char는 서명되지 않은 플랫폼에서 실패하기 때문에 사용 하는 것은 좋지 않습니다 .
milleniumbug

답변:


113

첫째, 사양은 0반드시 -1또는이 아닌 보다 작거나 같거나 큰 값을 반환한다는 것입니다 1. 둘째, 반환 값은 적분 승격이 적용되는 rvalue이므로 더 작은 값을 반환 할 필요가 없습니다.

C ++에서 (C에서와 같이) 모든 표현식은 rvalue 또는 lvalue입니다. 역사적으로 용어는 lvalue가 할당의 왼쪽에 나타나는 사실을 의미하며 rvalue는 오른쪽에만 나타날 수 있습니다. 오늘날, 비 클래스 유형에 대한 간단한 근사값은 lvalue는 메모리에 주소를 가지고 있지만 rvalue는 그렇지 않다는 것입니다. 따라서 rvalue의 주소를 사용할 수 없으며 cv 한정자 ( "액세스"조건)가 적용되지 않습니다. C ++ 용어로 클래스 유형이없는 rvalue는 객체가 아닌 순수한 값입니다. 함수의 반환 값은 참조 유형이없는 경우 rvalue입니다. (레지스터에 맞는 비 클래스 유형은 거의 항상 메모리가 아닌 레지스터에 반환됩니다.)

클래스 유형의 경우 rvalue에 대해 멤버 함수를 호출 할 있기 때문에 문제가 좀 더 복잡 합니다. 이것은 this cv-qualification이 오버로드 해결에서 역할을하기 때문에 rvalue는 실제로 포인터에 대한 주소를 가져야 하며 cv-qualified가 될 수 있음을 의미합니다. 마지막으로 C ++ 11은 rvalue 참조를 지원하기 위해 몇 가지 새로운 구별을 도입했습니다. 이것들도 주로 클래스 유형에 적용됩니다.

적분 승격은 an보다 작은 정수 유형 int이 표현식에서 rvalue로 사용될 때 대부분의 컨텍스트에서로 승격 된다는 사실을 의미 합니다 int. 따라서 변수가 선언 된 경우에도 short a, b;표현식 a + b에서 abint 추가가 발생하기 전에 승격됩니다 . 내가 쓰는 경우 마찬가지로 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 )는 통합 승격으로 인해 동일 합니다.

이 두 문제는 공식적으로 직교합니다. rvalue와 lvalue는 적분 승격과 관련이 없습니다. 제외 ... 적분 승격은 rvalue에만 적용되며 rvalue를 사용하는 경우 대부분 (전부는 아님)이 적분 승격으로 이어집니다. 이러한 이유로 인해 다음보다 작은 값으로 숫자 값을 반환 할 이유가 없습니다.int . 문자 유형으로 반환하지 않는 아주 좋은 이유도 있습니다. 과 같이 오버로드 된 연산자는 <<종종 문자 유형에 대해 다르게 동작하므로 문자를 문자 유형으로 만 반환하려고합니다. (차이점을 비교할 수 있습니다.

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

차이점은 두 번째 경우에는 추가로 인해 적분 승격이 발생하여의 다른 과부하 <<가 선택된다는 것입니다.


46
return values are rvalues, subject to integral promotion답변 에 더 자세히 설명해 주시면 좋을 것입니다.
Alvin Wong

"반환 값은 rvalue입니다 ... 따라서 더 작은 값을 반환 할 필요가 없습니다." LIKE IT
masoud

1
@AlvinWong : C 문자 리터럴이 문자 대신 정수인 이유에 대한 답변을 참조하십시오 . 자세한 배경 정보는
Jesse Good

귀하의 수정 사항이 추가 된 훌륭한 설명 후에 다시 +1 할 수 있기를 바랍니다.
코디 그레이

만약 그렇다면 signed char? 서명과 동일하게 작동 char합니까, 아니면 다른 유형입니까?
user541686

41

의도적으로 -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();
}

8
첫 번째 compare기능은 걸리는 경우 (다행히) 동일하게 적용하지 않는 것이 오버 플로우 문제가 char*char보다 작은입니다 int. 예를 들어, if *ais MAX_INTand *bis -1then *a - *b은 UB이지만 구현에서 동작을 정의하기로 선택하면 결과는 거의 확실하게 부정적입니다.
Steve Jessop

1
마지막 예의 문제 :를 length()반환합니다 size_t.이 값은 int… 보다 클 수 있습니다 .
F'x

예, 문자열 길이가 2GB 이상이면 문제가 될 수 있습니다. 한 번 fifo에 물건을 저장하는 테스트 케이스로 1GB의 긴 문자열을 수행했습니다. 하지만 ... 확인하는 MPEG를 포함하는 문자열을 다루는 사람이 Base64로로 인코딩 또는 일부 등은 물론 그 문제로 실행할 수 있습니다
매트 피터슨에게

@MatsPetersson은 "왜 int를 반환합니까?"라는
F'x 2013 년

글쎄요, 저는 그것이 히스테리 적이라고 확신합니다-제 말은 역사적인 이유를 의미합니다-아마도 strcmp / memcmp 및 기타 비교 유형 작업과 호환되기 때문일 것입니다.
Mats Petersson 2013 년

25

int는 일반적으로 (대부분의 최신 하드웨어에서 의미하는) 시스템 버스 및 / 또는 CPU 레지스터와 같은 크기의 정수이며,이를 기계어라고합니다. 따라서 int는 정렬, 마스킹 및 기타 작업이 필요하지 않기 때문에 일반적으로 더 작은 유형보다 빠르게 전달됩니다.

더 작은 유형은 주로 배열 및 구조체에 대한 RAM 사용 최적화를 허용하기 위해 존재합니다. 대부분의 경우 더 나은 RAM 사용을 위해 몇 개의 CPU주기 (결합 작업 형태)를 교환합니다.

반환 값을 부호가 있거나 부호가없는 센테 인 크기 (char, short…)로 강제 할 필요가 없다면 int를 사용하는 것이 더 낫습니다. 이것이 표준 라이브러리가 수행하는 이유입니다.


말이되는 방식으로 사물의 하드웨어 측면을 설명하는 훌륭한 방법입니다.
오우거 Psalm33

10

그것은 C-ism입니다.

C가 compare유형의 함수를 필요로 할 때 항상 int. C ++은 (안타깝게도)이 작업을 진행했습니다.

그러나 int일반적으로 사용중인 시스템의 레지스터 크기 이므로를 반환하는 것이 현실적으로 가장 빠른 방법 일 것입니다. (고의적으로 모호합니다.)


1
사실 shortchar예를 들어, 성능 저하를 부과 할 수 255+7A에 대한 다른 값이 charint반드시 단순히 저장할 수 없습니다 올바른 구현 그래서 char어디 int그 의미를 전달 돌보는없이 갈 수 있습니다. 컴파일러는 이것이 초래하는 비 효율성을 반드시 최적화하지는 않습니다.
Jack Aidley 2013 년

10

이 메서드는 실제로 집합에서 정수를 반환하지 않습니다 { -1, 0, 1 }. 실제로 모든 정수 값 이 될 수 있습니다 .

왜? 내가 생각할 수있는 주된 이유 int는 아키텍처의 "자연스러운 크기"값이어야 한다는 것입니다 . 이 크기의 값에 대한 작업은 일반적으로 더 작거나 큰 값에 대한 작업보다 적어도 빠릅니다 (많은 경우 더 빠름). 따라서 이것은 가장 빠른 것을 사용할 수 있도록 구현에 충분한 여유를 허용하는 경우입니다.


4

Foo 유형의 두 개체를 비교하는 비교 메서드를 디자인하고 -1, 0 또는 1 만 반환하려는 경우 일반적으로 short 또는 char를 사용하는 것이 좋은 생각일까요?

괜찮은 생각 일 것입니다. 더 좋은 방법은 bool (동일한 경우에만 비교하려는 경우) 또는 enum (자세한 정보)을 반환하는 것입니다.

enum class MyResult
{
  EQUAL,
  LESS,
  GREATER
};

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

3
"괜찮은 아이디어". 그것에 대한 근거가 있습니까?
jrok

4

어떤 사람들이 코드를 C에서 C ++로 변경한다고 가정 해 보겠습니다. 그들은 대체하기로 결정 strcmpstring::compare.

strcmp반품 이후 선물 intstring::compare반품 하기가 더 쉽습니다 int.


2

아마도이 반환 값 세트strcmp 가있는 것처럼 작동하도록 만들 수 있습니다 . 코드를 이식하려면 가능한 한 가깝게 쪼개지는 대체물을 사용하는 것이 더 직관적 일 것입니다.

또한 반환 값은 -1, 0또는 1뿐만 아니라 <0, 0또는 >0입니다.

또한 언급했듯이 수익은 완전한 프로모션의 대상 이므로 더 작게 만드는 것은 의미가 없습니다.


-1

부울 반환 값은 두 개의 가능한 값 (true, false) 만 가능하고 비교 함수는 세 개의 가능한 값 (작거나 같음,보다 큼)을 반환 할 수 있기 때문입니다.

최신 정보

당신이 경우, 서명 짧은을 반환 확실히 가능하지만 정말 자신의 비교 함수를 구현하고 싶어, 당신은 두 개의 논리 값과 니블 또는 구조체 값을 반환 할 수 있습니다.


7
질문의 어디에도 부울 유형 반환에 대해 언급하지 않습니다. 사실, 그는 구체적으로 제시 short하고 char대안으로 int.
Cody Gray
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.