Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistency between std::string and string literals

I have discovered a disturbing inconsistency between std::string and string literals in C++0x:

#include <iostream> #include <string>  int main() {     int i = 0;     for (auto e : "hello")         ++i;     std::cout << "Number of elements: " << i << '\n';      i = 0;     for (auto e : std::string("hello"))         ++i;     std::cout << "Number of elements: " << i << '\n';      return 0; } 

The output is:

Number of elements: 6 Number of elements: 5 

I understand the mechanics of why this is happening: the string literal is really an array of characters that includes the null character, and when the range-based for loop calls std::end() on the character array, it gets a pointer past the end of the array; since the null character is part of the array, it thus gets a pointer past the null character.

However, I think this is very undesirable: surely std::string and string literals should behave the same when it comes to properties as basic as their length?

Is there a way to resolve this inconsistency? For example, can std::begin() and std::end() be overloaded for character arrays so that the range they delimit does not include the terminating null character? If so, why was this not done?

EDIT: To justify my indignation a bit more to those who have said that I'm just suffering the consequences of using C-style strings which are a "legacy feature", consider code like the following:

template <typename Range> void f(Range&& r) {     for (auto e : r)     {         ...     } } 

Would you expect f("hello") and f(std::string("hello")) to do something different?

like image 632
HighCommander4 Avatar asked Jul 17 '11 23:07

HighCommander4


People also ask

What is the difference between std::string and string?

There is no functionality difference between string and std::string because they're the same type.

What is the difference between string and string literal in C?

C-strings are simply implemented as a char array which is terminated by a null character (aka 0 ). This last part of the definition is important: all C-strings are char arrays, but not all char arrays are c-strings. C-strings of this form are called “string literals“: const char * str = "This is a string literal.

Are string literals constant?

A String Literal, also known as a string constant or constant string, is a string of characters enclosed in double quotes, such as "To err is human - To really foul things up requires a computer." String literals are stored in C as an array of chars, terminted by a null byte.

Is std::string a literal type?

std::string literals (C++14)This kind of string literal produces a temporary object of type std::string , std::wstring , std::u32string , or std::u16string , depending on the prefix that is specified.


1 Answers

If we overloaded std::begin() and std::end() for const char arrays to return one less than the size of the array, then the following code would output 4 instead of the expected 5:

#include <iostream>  int main() {     const char s[5] = {'h', 'e', 'l', 'l', 'o'};     int i = 0;     for (auto e : s)         ++i;     std::cout << "Number of elements: " << i << '\n'; } 
like image 139
Howard Hinnant Avatar answered Sep 20 '22 16:09

Howard Hinnant