Can I make an assumption that given
std::string str;
... // do something to str
Is the following statement is always true?
Normally, yes.
But if someone decides to redefine an operator then all bets are off:
bool operator == (const std::string& a, const char b[])
{
return a != b; // paging www.thedailywtf.com
}
Yes (str.empty() == (str == ""))
is always* true for std::string
. But remember that a string
can contain '\0'
characters. So even though the expression s == ""
may be false, s.c_str()
may still return an empty C-string. For example:
#include <string>
#include <iostream>
using namespace std;
void test( const string & s ) {
bool bempty = s.empty();
bool beq = std::operator==(s, ""); // avoid global namespace operator==
const char * res = (bempty == beq ) ? "PASS" : "FAIL";
const char * isempty = bempty ? " empty " : "NOT empty ";
const char * iseq = beq ? " == \"\"" : "NOT == \"\"";
cout << res << " size=" << s.size();
cout << " c_str=\"" << s.c_str() << "\" ";
cout << isempty << iseq << endl;
}
int main() {
string s; test(s); // PASS size=0 c_str="" empty == ""
s.push_back('\0'); test(s); // PASS size=1 c_str="" NOT empty NOT == ""
s.push_back('x'); test(s); // PASS size=2 c_str="" NOT empty NOT == ""
s.push_back('\0'); test(s); // PASS size=3 c_str="" NOT empty NOT == ""
s.push_back('y'); test(s); // PASS size=4 c_str="" NOT empty NOT == ""
return 0;
}
**barring an overload of operator==
in the global namespace, as others have mentioned*
It should be. The ANSI/ISO standard states in 21.3.3 basic_string capacity:
size_type size() const;
Returns: a count of char-like objects currently in the string.
bool empty() const;
Returns:
size() == 0
However, in clause 18 of 21.3.1 basic_string constructors it states that the character-type assignment operator uses traits::length()
to establish the length of the controlled sequence so you could end up with something strange if you are using a different specialization of std::basic_string<>
.
I think that the 100% correct statement is that
(str.empty() == (str == std::string()))
or something like that. If you haven't done anything strange, then std::string("")
and std::string()
should be equivalent
They are logically similar but they are testing for different things. str.empty()
is checking if the string is empty where the other is checking for equality against a C-style empty string. I would use whichever is more appropriate for what you are trying to do. If you want to know if a string is empty, then use str.empty()
.
Some implementations might test for the null character as the first character in the string resulting in a slight speed increase over calculating the size of the string.
I believe that this is not common however.
Yes it is equivalent but allows the core code to change the implementation of what empty() actually means depending on OS/Hardware/anything and not affect your code at all. There is similiar practice in Java and .NET
Yes. Here is the relevant implementation from bits/basic_string.h
, the code for basic_string<_CharT, _Traits, _Alloc>
:
/**
* Returns true if the %string is empty. Equivalent to *this == "".
*/
bool
empty() const
{ return this->size() == 0; }
Even though the two forms are equivalent for std::string
, you may wish to use .empty()
because it is more general.
Indeed, J.F. Sebastian comments that if you switch to using std::wstring
instead of std::string
, then ==""
won't even compile, because you can't compare a string of wchar_t
with one of char
. This, however, is not directly relevant to your original question, and I am 99% sure you will not switch to std::wstring
.