C ++ string ==와 compare ()의 차이점은 무엇입니까?


363

방금 사용에 대한 몇 가지 권장 사항을 읽었습니다.

std::string s = get_string();
std::string t = another_string();

if( !s.compare(t) ) 
{

대신에

if( s == t )
{

나는 익숙해 져 있고 자연스럽고 가독성이 좋기 때문에 거의 항상 마지막 것을 사용하고 있습니다. 별도의 비교 기능이 있다는 것도 알지 못했습니다. 더 정확하게 말하면 ==는 compare ()를 호출한다고 생각했습니다.

차이점은 무엇입니까? 어떤 상황에서 어떤 방법이 다른 방법에 유리해야합니까?

문자열이 다른 문자열과 동일한 값인지 알아야하는 경우 만 고려하고 있습니다.


5
첫 번째 것은 true를 반환하고 후자는 false를 반환하고 그 반대도 마찬가지입니다.
Viktor Sehr

56
첫 번째는 거의 읽을 수 없지만 후자는 쉽게 읽고 이해할 수 있습니다.
Matthieu M.

3
"compare"함수를 다음과 같이 사용합니다 : if(x.compare(y) == 0)<-equals sign, equals. 사용 !하는 IMO 는 코드를 읽을 수 없게 만듭니다.
R. Martinho Fernandes

1
모든 경우에 ==가 작동하지는 않습니다. 문자열은 연산자를 오버로드하여 비교를 수행하므로 ==는 비교를 호출하는 것과 같습니다. 또는 == 연산자를 오버로드하지 않는 객체에서이 작업을 시도하면 내부 구성 요소가 아닌 메모리에서 주소를 비교하게됩니다. 비교 호출이 더 안전합니다. std :: string을 사용하는 경우 괜찮습니다.
DCurro

한 가지 차이점 : compare반환 -1하는 경우 s보다 낮은 t+1경우 s보다 큰 t동안 ==반환 true/false. 0이 아닌 정수는 true0입니다 false.
최규현

답변:


450

이것이 표준이 말하는 것입니다 operator==

21.4.8.2 연산자 ==

template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
                const basic_string<charT,traits,Allocator>& rhs) noexcept;

lhs.compare (rhs) == 0을 반환합니다.

큰 차이가없는 것 같습니다!


5
독자에 대한 참고 사항 : 관련 차이점이 있으므로 문제에 대한 자세한 내용은 Frédéric Hamidi의 답변 을 읽으십시오 . Bo Persson은 두 테스트가 모두 동일한 값을 반환한다는 것을 기쁘게 생각합니다. !s.compare(t)s == t같은 값을 반환하지만,이 기능은보다 더 많은 정보를 제공 비교합니다 s == t, 그리고 s == t당신은 상관하지 않을 때 더 읽을 수있는 방법 문자열이 있지만 다른 경우 가 다릅니다.
cdgraham

143

std :: string :: compare ()int다음을 리턴합니다 .

  • s및 같으면 0 과 t같고
  • 보다 작 으면 0 s보다 작다t .
  • 0보다 큰 경우 s 보다 큽니다 t.

첫 번째 코드 스 니펫이 두 번째 코드 스 니펫과 동일하게하려면 실제로 다음을 읽어야합니다.

if (!s.compare(t)) {
    // 's' and 't' are equal.
}

항등 연산자는 항등 (따라서 이름) 만 테스트하고 bool .

사용 사례를 자세히 설명하려면 compare() 두 문자열이 서로 다를 때 두 문자열이 서로 (어떻게) 관련되는지에 관심이있는 경우 유용 할 수 있습니다. PlasmaHH는 나무를 정당하게 언급하며, 예를 들어 컨테이너를 정렬하는 것을 목표로하는 문자열 삽입 알고리즘, 위에서 언급 한 컨테이너의 이분법 검색 알고리즘 등이 될 수 있습니다.

편집 : Steve Jessop이 주석에서 지적했듯이 compare()빠른 정렬 및 이진 검색 알고리즘에 가장 유용합니다. std :: less 만으로 자연 정렬 및 이분법 검색을 구현할 수 있습니다 .


이 동작은 나무 나 나무 같은 생물을 다룰 때 종종 유용합니다.
PlasmaHH

사실 그것은이다 나는 단지 방법 및 항등 연산자 : 차이점을 지적했다
프레데릭 Hamidi

"어느 상황에서 어느 쪽이 다른쪽에 유리해야합니까?" OP가 compare ()의 가능한 유스 케이스를 생각할 수 없다고 생각하게합니다.
PlasmaHH

2
"두 문자열이 서로 어떻게 관련되는지에 관심이 있다면"-관용적 C ++ std::less은 3 방향 비교기보다는 엄격한 약한 순서 ( 이 경우에는 총 순서 임 )를 사용하는 것이지만 . compare()모델로 작업입니다 std::qsortstd::bsearch모델로 그 반대로, std:sort하고 std::lower_bound.
Steve Jessop

30

compare하위 문자열을 비교하기위한 과부하가 있습니다. 전체 문자열을 비교하는 경우 ==연산자 를 사용해야 합니다 (호출 여부 compare는 거의 관련이 없습니다).


30

내부적으로 string::operator==()를 사용하고 string::compare()있습니다. 다음을 참조하십시오 : CPlusPlus-string::operator==()

성능을 비교하기 위해 작은 응용 프로그램을 작성했으며 디버그 환경에서 코드를 컴파일하고 실행하는 string::compare()경우 약간 더 빠릅니다.string::operator==() . 그러나 릴리스 환경에서 코드를 컴파일하고 실행하면 둘 다 거의 동일합니다.

참고로, 나는 그러한 결론을 내기 위해 1,000,000 반복을 실행했습니다.

디버그 환경에서 string :: compare가 더 빠른 이유를 증명하기 위해 어셈블리로 갔으며 코드는 다음과 같습니다.

디버그 빌드

문자열 :: 연산자 == ()

        if (str1 == str2)
00D42A34  lea         eax,[str2]  
00D42A37  push        eax  
00D42A38  lea         ecx,[str1]  
00D42A3B  push        ecx  
00D42A3C  call        std::operator==<char,std::char_traits<char>,std::allocator<char> > (0D23EECh)  
00D42A41  add         esp,8  
00D42A44  movzx       edx,al  
00D42A47  test        edx,edx  
00D42A49  je          Algorithm::PerformanceTest::stringComparison_usingEqualOperator1+0C4h (0D42A54h)  

문자열 :: 비교 ()

            if (str1.compare(str2) == 0)
00D424D4  lea         eax,[str2]  
00D424D7  push        eax  
00D424D8  lea         ecx,[str1]  
00D424DB  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0D23582h)  
00D424E0  test        eax,eax  
00D424E2  jne         Algorithm::PerformanceTest::stringComparison_usingCompare1+0BDh (0D424EDh)

string :: operator == ()에서 추가 작업을 수행해야한다는 것을 알 수 있습니다 (esp, 8 및 movzx edx, al 추가)

릴리스 빌드

문자열 :: 연산자 == ()

        if (str1 == str2)
008533F0  cmp         dword ptr [ebp-14h],10h  
008533F4  lea         eax,[str2]  
008533F7  push        dword ptr [ebp-18h]  
008533FA  cmovae      eax,dword ptr [str2]  
008533FE  push        eax  
008533FF  push        dword ptr [ebp-30h]  
00853402  push        ecx  
00853403  lea         ecx,[str1]  
00853406  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0853B80h)  

문자열 :: 비교 ()

            if (str1.compare(str2) == 0)
    00853830  cmp         dword ptr [ebp-14h],10h  
    00853834  lea         eax,[str2]  
    00853837  push        dword ptr [ebp-18h]  
    0085383A  cmovae      eax,dword ptr [str2]  
    0085383E  push        eax  
    0085383F  push        dword ptr [ebp-30h]  
    00853842  push        ecx  
00853843  lea         ecx,[str1]  
00853846  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0853B80h)

두 어셈블리 코드는 컴파일러가 최적화를 수행하는 것과 매우 유사합니다.

마지막으로, 필자의 의견으로는 성능 향상이 무시할만한 수준이므로 개발자가 동일한 결과를 달성 할 때 (특히 릴리스 빌드 일 때) 어느 것이 선호되는지 결정하도록 개발자에게 맡길 수 있습니다.


10
'매우 비슷합니다 .... 차이가 없습니다.
xtofl

나도 ... 그들은 같은 것입니다. 차이가 없습니다
Wagner Patriota

1
Tony의 예제에서 @xtofl 생성 된 코드는 릴리스 빌드에서 동일하며 디버그 빌드에서는 다릅니다.
JulianHarty

6

compare()strcmp ()와 같습니다. ==단순한 평등 검사입니다. compare()따라서를 반환 int, ==부울입니다.


5

compare()돌아올 것이다 false.0 문자열이 동일한 경우).

그러므로 서로를 교환하는 것을 가볍게하지 마십시오.

더 읽기 쉬운 코드를 사용하십시오.


3

문자열 동등성을 확인하려면 == 연산자를 사용하십시오. 두 개의 문자열이 같은지 확인하는 것은 순서를 찾는 것보다 간단합니다 (compare ()가 제공하는 것). 등식 연산자를 사용하는 것이 성능면에서 더 나을 있습니다.

더 긴 답변 : API는 문자열 동등성을 확인하는 방법과 문자열 순서를 확인하는 방법을 제공합니다. 문자열 등식을 원하므로 등식 연산자를 사용하십시오 (예측과 라이브러리 구현 자의 기대 값이 일치하도록하십시오). 성능이 중요한 경우 두 메소드를 모두 테스트하고 가장 빨리 찾을 수 있습니다.


2

두 개의 문자열 s와 t를 고려하십시오.
그들에게 몇 가지 가치를주십시오. (s == t)를
사용하여 비교 하면 부울 값 (true 또는 false, 1 또는 0)을 반환합니다. 그러나 s.compare (t)를 사용하여 비교할 때 표현식은 값 (i) 0 -s와 t가 같은 경우 (ii) <0 -s의 첫 번째 일치하지 않는 문자의 값이 s의 값보다 작은 경우 t 또는 s의 길이는 t의 길이보다 작습니다. (iii) > 0 -t에서 첫 번째로 일치하지 않는 문자의 값이 s의 값보다 작거나 t의 길이가 s의 값보다 작은 경우




1

여기서 다루지 않은 한 가지는 문자열을 c 문자열로, c 문자열을 문자열로 또는 문자열을 문자열로 비교하는지 여부에 달려 있다는 것입니다.

큰 차이점은 두 문자열을 비교하기 위해 비교하기 전에 크기가 동일한 지 확인하고 == 연산자를 비교하는 것보다 빠릅니다.

다음은 g ++ 데비안 7에서 볼 때의 비교입니다.

// operator ==
  /**
   *  @brief  Test equivalence of two strings.
   *  @param __lhs  First string.
   *  @param __rhs  Second string.
   *  @return  True if @a __lhs.compare(@a __rhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __lhs.compare(__rhs) == 0; }

  template<typename _CharT>
    inline
    typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
    operator==(const basic_string<_CharT>& __lhs,
           const basic_string<_CharT>& __rhs)
    { return (__lhs.size() == __rhs.size()
          && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
                            __lhs.size())); }

  /**
   *  @brief  Test equivalence of C string and string.
   *  @param __lhs  C string.
   *  @param __rhs  String.
   *  @return  True if @a __rhs.compare(@a __lhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const _CharT* __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __rhs.compare(__lhs) == 0; }

  /**
   *  @brief  Test equivalence of string and C string.
   *  @param __lhs  String.
   *  @param __rhs  C string.
   *  @return  True if @a __lhs.compare(@a __rhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const _CharT* __rhs)
    { return __lhs.compare(__rhs) == 0; }

코드는 편집기에서 형식화되고 형식화되어 표시됩니다. 디스플레이에 문제가 있습니다. basic_string.h를 열고 OS에서 operator ==를 찾으십시오. 코드는 내 것이 아닙니다. 크기 검사 가이 스레드에서 누락 된 것입니다. 또한 많은 사람들이 잘못된 정보에 동의하며 이는 스택 오버플로의 유틸리티를 무시합니다.
Dragos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.