tags:

views:

441

answers:

6

Why doesn't the STL string class have an overloaded char* operator built-in? Is there any specific reason for them to avoid it?

If there was one, then using the string class with C functions would become much more convenient.

I would like to know your views.

+12  A: 

You should always avoid cast operators, as they tend to introduce ambiguities into your code that can only be resolved with the use of further casts, or worse still compile but don't do what you expect. A char*() operator would have lots of problems. For example:

string s = "hello";
strcpy( s, "some more text" );

would compile without a warning, but clobber the string.

A const version would be possible, but as strings must (possibly) be copied in order to implement it, it would have an undesirable hidden cost. The explicit c_str() function means you must always state that you really intend to use a const char *.

anon
so, __string s = "hello"; strcpy(x, s.c_str());__ has two copy operations?
Sahasranaman MS
Possibly. Most std::string implementations actually tack a null-terminator onto their internal rep, so no copy is required, but the Standard does not forbid a copy. The answer to such problems of course, is not to use char *, const or otherwise, except for legacy APIs.
anon
@Sahasranaman: if you take a look into Martin's answer (string internal data is not necessarily contiguous) you'll see some cases (possible STL implementations) for which the copy is required. Then again it will not be so in C++0x where contiguity is a requirement. I don't know of any STL implementation where the storage is not contiguous anyway, so in real life .c_str() and .data() both return a pointer into the internal buffer with no copies.
David Rodríguez - dribeas
+5  A: 

The string template specification deliberately allows for a "disconnected" representation of strings, where the entire string contents is made up of multiple chunks. Such a representation doesn't allow for easy conversion to char*.

However, the string template also provides the c_str method for precisely the purpose you want: what's wrong with using that method?

Martin v. Löwis
There is nothing wrong with using c_str(), she's saying it would be more convenient if there is no need to use the c_str() too.
Sahasranaman MS
I think 'chunks' bad idea - c_str allows iteration over entire string without gaps.
Dewfy
I disagree with you. Having to think about the cast here is a wise thing. Martin provides a good explanation why it is so.
Anna
rope implementation (i.e. using multiple chunks) improves insert /delete performance - at least in theory. Also, std:.string iterators still allow iteration "without gaps".
peterchen
@Sahasranaman: it's not clear to me whether the OP is aware of c_str; I would find it surprising that a char* operator would be described as _much_ more convenient than c_str. @Dewfy: this is precisely the reason for c_str to exist. If string is implemented with a rope, c_str will need to reorganize it. There are specific constraints for how long the pointer returned by c_str remains valid, so it is useful that you have to call it explicitly - for an implicit conversion operator, you may not be aware that you are not supposed to change the string object.
Martin v. Löwis
@Martin: It would be convenient to use, __string s="hello"; strcpy(x, s);__ instead of __string s="hello"; strcpy(x, s.c_str());__. There have been several situations for me too where I had to use legacy functions to achieve inter-op with older code. I don't find anything wrong in saying an overloaded char* operator is easier to use than c_str when dealing with C functions like strcpy.
Sahasranaman MS
C++0x will mandate contiguous storage for std::basic_string, but will not provide a cast operator to charT*. I think this means that while your argument provides a sound case why the current string API can't comfortably support implicit conversion, it does not reflect the reasoning of the standards committee.
Steve Jessop
+2  A: 

You can use c_str instead:

string s("I like rice!");
const char* cstr = s.c_str();

I believe that in most cases you don't need the char*, and can work more conveniently with the string class itself.

Anna
+1: both can and should work with the string class itself :)
David Rodríguez - dribeas
+1  A: 

By 1998-2002 it was hot topic of c++ forums. The main problem - zero terminator. Spec of std::?string allows zero character as normal, but char* string doesn't.

Dewfy
+15  A: 

Following is the quote from Josuttis STL book:

However, there is no automatic type conversion from a string object to a C-string. This is for safety reasons to prevent unintended type conversions that result in strange behavior (type char* often has strange behavior) and ambiguities (for example, in an expression that combines a string and a C-string it would be possible to convert string into char* and vice versa). Instead, there are several ways to create or write/copy in a C-string, In particular, c_str() is provided to generate the value of a string as a C-string (as a character array that has '\0' as its last character).

Naveen
Where I work we have a legacy library that does have a string with automatic type conversion to const char*. I can't count number of times we've been bitten by application developers adding a string and an integer assuming they'll have formatting and concatenation and resulting in very bad things ...
Nikolai N Fetissov
A: 

If you need interop with C-style functions, using a std::vector<char> / <wchar_t> is often easier.

It's not as convenient, and unfortunately you can't O(1)-swap it with a std::string (now that would be a nice thing).

In that respect, I much prefer the interface of MFC/ATL CString which has stricter performance guarantees, provides interop, and doesn't treat wide character/unicode strings as totally foreign (but ok, the latter is somewhat platform specific).

peterchen