C++: is string.empty() always equivalent to string == ""?

C++String

C++ Problem Overview


Can I make an assumption that given

std::string str;
... // do something to str

Is the following statement is always true?

(str.empty() == (str == ""))

C++ Solutions


Solution 1 - C++

Answer

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; }
Discussion

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.

Solution 2 - C++

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().

Solution 3 - C++

str.empty() is never slower, but might be faster than str == "". This depends on implementation. So you should use str.empty() just in case.

This is a bit like using ++i instead of i++ to increase a counter (assuming you do not need the result of the increment operator itself). Your compiler might optimise, but you lose nothing using ++i, and might win something, so you are better off using ++i.

Apart from performance issues, the answer to your question is yes; both expressions are logically equivalent.

Solution 4 - C++

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

Solution 5 - C++

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.

Solution 6 - C++

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
}

Solution 7 - C++

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichaelView Question on Stackoverflow
Solution 1 - C++A. RexView Answer on Stackoverflow
Solution 2 - C++D.ShawleyView Answer on Stackoverflow
Solution 3 - C++GorpikView Answer on Stackoverflow
Solution 4 - C++jwfearnView Answer on Stackoverflow
Solution 5 - C++Jesse DearingView Answer on Stackoverflow
Solution 6 - C++John CarterView Answer on Stackoverflow
Solution 7 - C++Ray BooysenView Answer on Stackoverflow