Click here to Skip to main content
15,886,740 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello,

I'm writing an application which needs a lot of string manipulation.
I tried to use std::string, std::wstring(unicode) and CString. Sometimes, I use them together.

- What are the pros and the cons of using each of them?
- I'm curious about CString::GetBuffer(nMinBufLength). Here, what is nMinBufLength actually for? Is it for some memory optimization?
- Difference of functions of old function and new functino postfixed by _s. For example, strcpy and strcpy_s.
- I'm trying to put log to the local file. What is the fastest and efficient way between using CFile, FILE *, HANDLE (ReadFile/WriteFile) ?

There are too many standards in C++ language. I'm wondering which standard to choose for best speed.

Thank you.
Posted
Comments
Eugen Podsypalnikov 20-Mar-13 8:47am    
The best way is your way... Of course :)
Sergey Alexandrovich Kryukov 20-Mar-13 9:31am    
There are not too many standards. Only std::string is standard.
—SA

At the lowest level you have the core C library functions like strcpy and memmove which deal with bytes and are both fast and unsafe in that there is little checking of anything, you have to get the parameters right to avoid crashing and you might have to manage things like NULL terminating strings yourself and very carefully.

Then there are slightly more advanced C library functions like tcsncmp and strnicmp_s which deal with 2-byte or even variable byte characters forming UTF-8 or UNICODE strings and in the case of _s functions extra checking is added to try and prevent buffer overruns and other horrible accidents that result from bad parameters. The _s functions are Microsoft specific so you won't find them on Linux or OSX.

Next up the scale are proper C++ classes for dealing with strings. The C++ standard library has std::string, MFC and ATL have CString and its descendents, Qt has QString and most other frameworks will have their own possibly building on std::string and possibly ignoring it, possibly using the C library functions internally as CString used to and may still or possibly reimplementing the same sort of things their own way.

Which is best?

That depends what you're doing and what you want in terms of performance vs safety vs advanced functionality.
Are you working on an embedded system where you're strings are really short array of memory bytes being transferred to and from devices and files? Use the core C library functions.

Are you managing strings for a complex UI where you'll need translations in 18 languages? Qt will make this much easier with the advanced features of QString and related classes.

Are you working on an existing MFC/ATL application? Stick with CString and its ATL/WTL relatives for consistency. It works and the performance is not terrible as long as you're careful.

Are you working on a new C++ application where performance is important but you also want to get it done in this lifetime? Use std::string. It's safe, it's fast and it does most stuff OK.


The same sort of considerations apply to files except that on Windows the C library FILE functions actually call the Win32 functions so it's always faster, more efficient and also easier to use the Win32 file functions or a wrapper like CFile if your framework provides one.
 
Share this answer
 
Comments
Paul Zheng 20-Mar-13 12:57pm    
First of all, I appreciate your help, Matthew. My service is not critical for speed of string manipulation. It is just a service which runs on windows. I asked the string manipulation as I had trouble in working with string.

If I create a new project in vs2008, it will have UNICODE parameter set by default. So wchar will be defined as TCHAR and most of string functions refer to unicode-characters.
But some functions, for example fwrite(), only supports multibyte version, which accepts char* only. So I had to use wcstombs or mbstowcs to convert between wide char string and multi byte strings.
Matthew Faithfull 20-Mar-13 13:22pm    
No problem. If you're using std::string then I would not mix that with fwrite. I'd probably use std::ofstream which will be designed and tested to work together with std::string.
Espen Harlinn 20-Mar-13 14:22pm    
Excellent :-D
Monjurul Habib 20-Mar-13 15:16pm    
5++
Solution #1 is good (but IMHO didn't answer all the questions).

I have used both CString and std::string in my travels and my feelings are that std::string is newer than CString but in my observation not as robust. CString is Microsoft-only (so not portable, but if you move your code base to another platform, you could write a complete linux CString class in about 30 minutes). Both classes give you a class that packages an array of "const char*" that can be manipulated in various ways (CString wins on features).

CString will give you a reference to const char* out of the box but with std::string, you have to ask for it with the c_str() method.

CString also allows you to reference a "char*" (ie. write access) with the GetBuffer() API. If you just use CString::GetBuffer(), then you are handed the current object as a non-const string. It is your responsibility to know how long it is. If you give a value to GetBuffer() then the buffer is resized to a minimum of that value. In other words:

C++
CString str1 = "123";  // at least 4 bytes long
CString str2 = "123";  // at least 4 bytes long
char* p1 = str1.GetBuffer();  // You can write up to 4 chars
char* p2 = str2.GetBuffer(256);  // You can write up to 256 chars


CString has better internationalization characteristics that std::string.

std::string is considered more modern and unafflicted with association with MFC and ATL, so you will get a lot of people telling you that CString is "bad" without very good explanations. [Also, CString was originally bundled with MFC, but was separated into its own library somewhere around VS4.2. If anybody tells you that CString is an MFC class, they have been wrong since about 2001.]

Joseph Newcomer has written an excellent CString resource which can be found here[^].

I'm not sure about std::string but CString is reference counted so that you can do several interesting things with it. eg.:

C++
CString GimmeAString()
{
   CString str = "Blah Blah";  // on the stack
   return str;
}


Note that str is created on the stack, then returned. This is normally bad juju but since the stack object points to chars on the heap and reference counted, the ref count goes to 2, the stack object is deleted (but not the heap allocation) and a valid string is returned by the method even though the stack object is gone. I consider this a questionable feature since it saves you from failure in the case of doing something dumb.

As for the strcpy() vs strcpy_s() functions, the original crt provides strcpy(), which is standard and portable. The "_s" functions are Microsoft only and provide length checking for memory movement. For example:

C++
char s1[5];
strcpy(s1, "Hello World");  // no compile or runtime check, stack overrun
strcpy_s(s1, "Hello World");  // compile time error message

char* p1 = new char[5];
strcpy(p1, "Hello World");  // no compile or runtime check
strcpy_s(p1, 5, "Hello World");  // runtime exception
 
Share this answer
 
Comments
Espen Harlinn 20-Mar-13 14:23pm    
Very good :-D
H.Brydon 20-Mar-13 14:40pm    
Thank you sir. Noted and appreciated.
nv3 20-Mar-13 15:03pm    
Excellent summary, and I share your preference for CString.
H.Brydon 20-Mar-13 16:19pm    
Thanks muchly!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900