Thanks to Rick and Charlie, who located and fixed a head-scratching bug in my code. This bug is because when I compare two wraps of std::string, I compare char by char. However, the correct way should be comparing unsigned-char by unsigned char. Since my compare generate different results as std::string::compare, my code work in a wield way.
Here follows how std::string::compare and memcmp works in their GNU implementation:
std::string and std::wstring are realizations of class template basic_string (defined in <header-prefix>/c++/<version>/bits/basic_string.h, and <header-prefix> is usually /usr/include). basic_string::compare invokes char_traits<char>::compare (for std::string) or char_traits<wchar_t>::compare (for std::wstring). The former invokes memcpy and the latter invokes wmemcmp. So you see the C++ implementation depends on C implementation.
I downloaded the source tarball of glibc-2.12.1. In glibc-2.12.1/string/memcmp.c, there is the implementation of memcmp, which compares two strings byte-by-byte, and byte is defined in the same file as unsigned char. In glibc-2.12.1/wcsmbs/wmemcmp.c, there is wmemcmp, which compares two strings wint_t by wint_t, and wint_t is defined in include/wctype.h as unsigned int (unsigned again).
I also checked glibc-2.12.1/string/strcmp.c, where strcmp also compares unsigned char by unsigned char.
So both C and C++ compare string by treating each character an unsigned value.