Why does --string::end() compile but --string.size() does not?

strlen
string length c++
c++ string
c++ string length vs size
length of char array - c++
sizeof(string c++)
size of string java
size of string in c

The code

std::string str{ "foo" };
auto lastCharIndex{ --str.size() };

creates a compiler error lvalue required as decrement operand but

auto lastCharIterator{ --str.end() };

does not. Why is this?

string::size returns a scalar type (some kind of integer), by value, and the built-in prefix--- expression is not allowed on prvalues. By contrast, for overloaded operators (on user-defined types), which are essentially just functions, no such restriction applies. Whether --str.end() is allowed therefore depends on whether string::iterator is a user-defined type (some sort of class type) or a scalar type (e.g. a pointer). This is not specified, though, and may even vary depending on optimization settings.

Difference between strlen() and sizeof() for string in C, Evaluation size: sizeof() is a compile-time expression giving you the size of a In context of C++: In C++, you do not need any of them as such. strlen() in C-style strings can be replaced by C++ std::strings. Since size of char in C is 1 byte but then also we find that strlen() gave Don't stop learning now. The answer is potentially no. Microsoft does not guarantee that the layout of C++ classes will not change between between versions of the compiler. If you read the list of changes between compiler versions, there are always entries stating how the C++ standard library classes have been updated because of bug fixes and conformance.

I'd like to add that you can customize user-defined member functions like ++ that behave differently when called through lvalue and rvalue references. For example, you could define a custom iterator class that prevents you from calling modifying member functions on a temporary. To do this, you need to use reference qualifiers.

class iterator {
public:
    iterator operator++() & { // for lvalues
        std::cout << "incrementing...\n";
    }
    iterator operator++() && = delete; // for rvalues
};

With these qualifiers, you still allow lvalues to be modified:

iterator it = ...;
++it; // totally fine

but you can now prevent temporaries from being modified, which results in a user-defined class that is more consistent with built-in types like the size_t.

++(iterator{}); // ERROR

Live example here

I'm not sure what the standard says about this for std::string's iterator type, but in principle, you could do this for your own iterators and other classes, wherever you think it's always an mistake to modify a temporary.

5 Different methods to find length of a string in C++, We say a paragraph'ss length not its size, so length() is to make things more readable. Using string::size: The method string::size returns the length of the string, char *str) computes the length of the string str up to, but not including the from starting of string to end of string (terminating null character). As we’re not modifying any of the strings, it makes more sense to not waste time creating a temporary string, as we can directly work with references. NOTE : From C++20 onward, many of the standard library methods are now constexpr compatible, so they are executed during compile time itself.

The operand of the decrement (and increment) operator for fundamental types arithmetic types must be an lvalue. std::string::size returns a value (i.e. not a reference) of an integer type, so the function invocation str.size() is a prvalue. Prvalues are not lvalues, so --str.size() is ill-formed.

The operand of the decrement (and increment) operator overload for a class type may be called on an rvalue unless the overload is lvalue ref-qualified. If --str.end() is well-formed, then we can deduce that the iterator is a class type (pointer would be an example of a iterator type that is not a class type) and the decrement operator overload indeed does not have a lvalue ref-qualifier. As far as I can tell, whether member functions of iterators of standard containers are ref-qualified is unspecified.

P.S. Same applies to (compound) assignment operators: The left hand operand of an assignment must also be an lvalue (unless it is a class type with an overload that is not lvalue ref-qualified). In fact, this is where the "l" in lvalue originates.

string::length - C++ Reference, Therefore, the value returned may not correspond to the actual number of Both string::size and string::length are synonyms and return the exact same value. string::length #include <iostream> #include <string> int main () { std::string str ( " Test string" ); std::cout << "The size of str is " << str.length() << " bytes. string:: end. Evaluation size: sizeof() is a compile-time expression giving you the size of a type or a variable’s type. It doesn’t care about the value of the variable. Strlen on the other hand, gives you the length of a C-style NULL-terminated string.

6.6 — C-style strings, This means you can initialize the string upon creation, but you can not assign In this case, the string “Alex” will be printed, and std::cout will stop at the null strncat() -- Appends one string to another (with buffer length check) I can check if the program is OK online on the website ( it uses a C++11 / C++14 compiler). Strings (C# Programming Guide) 06/27/2019; 12 minutes to read +12; In this article. A string is an object of type String whose value is text. Internally, the text is stored as a sequential read-only collection of Char objects.

17.3 — std::string length and capacity, The length of the string is quite simple -- it's the number of characters in the string. use length() to determine whether a string has any characters or not, There is one more size-related function that you will probably never use, but we'll multiple times by immediately setting the string to its final capacity:� This is an easy mistake to make when you are working with functions that take string arguments; those arguments are always pointers, not arrays. It must also be noted that for multibyte encoded strings the return value does not have to correspond to the number of characters in the string.

Chapter 8: Strings, The end of the string is marked with a special character, the null character Because C has no built-in facilities for manipulating entire arrays (copying them, This is the only case where the compiler sizes a string array for us, however; used what may at first appear to be an infinite loop--the controlling expression is the� Therefore, the value returned may not correspond to the actual number of encoded characters in sequences of multi-byte or variable-length characters (such as UTF-8). Both string::size and string::length are synonyms and return the exact same value. Parameters none Return Value The number of bytes in the string.

Comments
  • Because string::end() is a string.iterator() and has a defined operator --().
  • Possible duplicate of Why can't I decrement std::array::end()?
  • Also relevant: how portable is end iterator decrement?
  • because they are two different function. they do different thing. (yes, this is for string, but generically functions can return anything, they may simply return a const object (with overloaded operator--) and you still cannot decrements it)