tags:

views:

697

answers:

12

I am a C programmer,now trying to write c++ code.I heard string in C++ was better than char* in terms of security, performance, etc,but sometimes it seems that char * is better choice.Someone suggest that programmer should not use char * in C++ becuase we could do all things that char * could do with string, and its securer and faster.

So do you ever used char* in C++?and what are the specific conditions?

ps: edit a lot, to clarify the problem.

+20  A: 

It's safer to use std::string because you don't need to worry about allocating / deallocating memory for the string. The C++ std::string class is likely to use a char* array internally. However, the class will manage the allocation, reallocation, and deallocation of the internal array for you. This removes all the usual risks that come with using raw pointers, such as memory leaks, buffer overflows, etc.

Additionally, it's also incredibly convenient. You can copy strings, append to a string, etc., without having to manually provide buffer space or use functions like strcpy/strcat. With std::string it's as simple as using the = or + operators.

Basically, it's:

 std::string s1 = "Hello ";
 std::string s2 = s1 + "World";

versus...

 const char* s1 = "Hello";
 char s2[1024]; // How much should I really even allocate here?
 strcpy(s2, s1);
 strcat(s2, " World ");

Edit:

In response to your edit regarding the use of char* in C++: Many C++ programmers will claim you should never use char* unless you're working with some API/legacy function that requires it, in which case you can use the std::string::c_str() function to convert an std::string to const char*.

However, I would say there are some legitimate uses of C-arrays in C++. For example, if performance is absolutely critical, a small C-array on the stack may be a better solution than std::string. You may also be writing a program where you need absolute control over memory allocation/deallocation, in which case you would use char*. Also, as was pointed out in the comments section, std::string isn't guaranteed to provide you with a contiguous, writable buffer, so you can't directly write from a file into an std::string if you need your program to be completely portable. However, in the event you need to do this, std::vector would still probably be preferable to using a raw C-array.

Charles Salvia
At times, using string is harder though. Its trivial to turn a byte stream into a null terminated char *. It's not so trivial with std::string though
Earlz
@earlz: I consider calling a function (`std::string::c_str()`) rather trivial.
sbi
std::string has a constructor for that.
Matt Kane
Roger Pate
@Roger: that's actually a good point. Since std::string is not guaranteed to have a contiguous internal buffer, you can't safely do things like read directly into a string from a file.
Charles Salvia
The only valid reason to use `char *` as far as I have constated is when delivering an API to a client that may not have the same STL than you do :/
Matthieu M.
One simple reason to use char* instead of string is if you have to avoid dynamic memory allocation (i.e. perhaps in an interrupt handler or on an embedded system).
Adisak
I think that all of the exceptions come down to, use char* if you know that you have to. If you don't have a good reason (and most of the time you don't), use std::string.
KeithB
Another specific instance to prefer char* over std::string is where you need a static string constant. If have static std::string instances (in a cpp file or as static class members) then you may run into order-of-initialisation problems. Using a raw char* avoids this problem.
the_mandrill
+1  A: 

String may actually be better in terms of performance. And innumerable other reasons - security, memory management, convenient string functions, make std::string an infinitely better choice.

Edit: To see why string might be more efficient, read Herb Sutter's books - he discusses a way to internally implement string to use Lazy Initialization combined with Referencing.

Fox
I'd +1 if you give more info on how strings are more efficient. Just a summary/conclusions, I can go get the book if I want the details.
caspin
I think he's referring to Copy-on-Write semantics, which, is actually a bad idea these days due to multi-threading.
Charles Salvia
If you are referring to copy-on-write, then time has proven worth and at the end it seems that copy-on-write will not improve performance over current early copy implementations. Copy-on-write has many problems with multithreading and the solutions require exclusive locks that have more costs than the gain that copy-on-write provides.
David Rodríguez - dribeas
Some things that are more efficient: getting the size of a string is a constant time operation in std::string but linear time on the size of the string with const char*, and thereof any operation that requires calculating the size of the string
David Rodríguez - dribeas
@Charles, Dribeas, Caspin - It *is* copy-on-write semantics I was referring to, and I see your point (though I'll have to weigh out the pros and cons). Thanks.
Fox
+2  A: 

C char * strings cannot contain '\0' characters. C++ string can handle null characters without a problem. If users enter strings containing \0 and you use C strings, your code may fail. There are also security issues associated with this.

Mark Byers
In both C and C++, char * strings point to regular memory arrays. If you really want to, you can embed extra '\0' characters in them. A common performance trick when parsing things like file system paths is to temporarily "truncate" a string by swapping out characters with '\0'. Another common use it to represent a list of strings in a single array, using '\0' for delimiters with a double-NULL at the very end.
Kurt
More correctly, the C string functions (strcpy, etc.) cannot handle '\0', since they use it as an end of string marker. If you are willing to write your own fuctions, char* can contain '\0' just fine.
KeithB
+4  A: 

Ok, the question changed a lot since I first answered.

Native char arrays are a nightmare of memory management and buffer overruns compared to std::string. I always prefer to use std::string.

That said, char array may be a better choice in some circumstances due to performance constraints (although std::string may actually be faster in some cases -- measure first!) or prohibition of dynamic memory usage in an embedded environment, etc.

Fred Larson
+3  A: 

In general, std::string is a cleaner, safer way to go because it removes the burden of memory management from the programmer. The main reason it can be faster than char *'s, is that std::string stores the length of the string. So, you don't have to do the work of iterating through the entire character array looking for the terminating NULL character each time you want to do a copy, append, etc.

That being said, you will still find a lot of c++ programs that use a mix of std::string and char *, or have even written their own string classes from scratch. In older compilers, std::string was a memory hog and not necessarily as fast as it could be. This has gotten better over time, but some high-performance applications (e.g., games and servers) can still benefit from hand-tuned string manipulations and memory-management.

I would recommend starting out with std::string, or possibly creating a wrapper for it with more utility functions (e.g., starts_with(), split(), format(), etc.). If you find when benchmarking your code that string manipulation is a bottleneck, or uses too much memory, you can then decide if you want to accept the extra risks and testing that a custom string library demands.

TIP: One way of getting around the memory issues and still use std::string is to use an embedded database such as SQLite. This is particularly useful when generating and manipulating extremely large lists of strings, and performance is better than what you might expect.

Kurt
+1  A: 

Use std::string for its incredible convenience - automatic memory handling and methods / operators. With some string manipulations, most implementations will have optimizations in place (such as delayed evaluation of several subsequent manipulations - saves memory copying).

If you need to rely on the specific char layout in memory for other optimizations, try std::vector<char> instead. If you have a non-empty vector vec, you can get a char* pointer using &vec[0] (the vector has to be nonempty).

orip
In this case, I'd also recommend explicitly wrapping string functions to handle a NULL delimiter - just setting a vector of chars does not delimit it.
Fox
A: 

strlen(infinitelengthstring) vs string.length()

Pod
+1  A: 

Short answer, I don't. The exception is when I'm using third party libraries that require them. In those cases I try to stick to std::string::c_str().

larsm
A: 

In all my professional career I've had an opportunity to use std::string at only two projects. All others had their own string classes :)

Having said that, for new code I generally use std::string when I can, except for module boundaries (functions exported by dlls/shared libraries) where I tend to expose C interface and stay away from C++ types and issues with binary incompatibilities between compilers and std library implementations.

Nemanja Trifunovic
Most libraries have been in development for a long time, and offer their own string function. Most of these (the well maintained ones at least) offer a way to convert to and from std::string. Even if they don't, using the c_str() function for std::string to convert to c-string at the interface point is probably a good idea. I'll go out on a limb and say, wrap every vendor API up in your own API - makes it easier to transition between libraries, and port away from obsolete libraries (read, those with no time to even code in support for std::string).
Fox
A: 

std::string is almost always preferred. Even for speed, it uses small array on the stack before dynamically allocating more for larger strings.

However, char* pointers are still needed in many situations for writing strings/data into a raw buffer (e.g. network I/O), which can't be done with std::string.

Inverse
Your comment about `std::string` using small arrays on the stack is not necessarily true. It's just an implementation detail that *some* implementors may use, not an inherent advantage to std::string
Charles Salvia
A: 

The only time I've recently used a C-style char string in a C++ program was on a project that needed to make use of two C libraries that (of course) used C strings exclusively. Converting back and forth between the two string types made the code really convoluted.

I also had to do some manipulation on the strings that's actually kind of awkward to do with std::string, but I wouldn't have considered that a good reason to use C strings in the absence of the above constraint.

ceo
A: 

Implementations of std::string hide the memory usage from you. If you're writing performance-critical code, or you actually have to worry about memory fragmentation, then using char* can save you a lot of headaches.

For anything else though, the fact that std::string hides all of this from you makes it so much more usable.

tsalter