CString In A Nutshell
- Passing CString by value is bad
- Using CString causes memory fragmentation
- CString is slow
Inside CString
The CString data type is 32 bits. Passing CString by value is no more bulky than passing an int by value. You can verify this with an assertion ASSERT(sizeof(CString) == 4);
class CString
{
...
LPTSTR m_pchData; // pointer to ref counted string data
};
This is the "header" structure of every string:
struct CStringData
{
long nRefs; // reference count
int nDataLength; // length of data
int nAllocLength; // length of allocation
// TCHAR data[nAllocLength+1]
TCHAR* data() // TCHAR* to managed data
{ return (TCHAR*)(this+1); } // this+1 == ((void*)this)+12
};
Lets say you create a CString object like this:
CString str("hello");
First CString calls CString::AllocBuffer(5). This actually allocates 5 + 1 + 12 bytes (chunk + EOS + CStringData). nAllocLength will be set to 5 as will nDataLength. You might think that nDataLength should be 18, but since the extra 13 bytes are ALWAYS allocated, it's more efficient for CString to leave off those extra 13. In release builds, your strings are allocated in blocks of 64, 128, 256, or 512, this is where nDataLength comes in handy. In the case of our 5 character string, nDataLength would be 64. Using blocks reduces memory fragmentation and speeds up operations like adding. Reduction of memory fragmentation is achieved by the use of CFixedAlloc. This class never actually frees the memory allocated (until it is destroyed or explicitly told to), but returns free'd blocks to it's "free pool", so no memory fragmentation occurs. CFixedAlloc can be found in the MFC source directory in FIXEDALLOC.H and FIXEDALLOC.CPP if your curious. For strings larger than 512 characters, the memory is allocated and freed the same as in debug builds.
nRefs is set to 1
m_pchData is set like this: m_pchData = pData->data(); pData is the block of memory allocated by AllocBuffer and cast to CStringData. So what we get looks like this:
1 5 5 h e l l o \0
---- ---- ---- - - - - - - <-bytes
^m_pchData
Of course to free the block of memory, CString cannot free m_pchData, but instead frees (BYTE*)GetData(); GetData() returns ((CStringData*)m_pchData)-1. Remember that it's casting the pointer to a 12-byte structure and subtracting one structure from it (or 12 bytes).
Reference Counting
So how does reference counting help speed things up? Whenever you use the copy constructor or the operator=(const CString& stringSrc), the only thing that happens is this:
m_pchData = stringSrc.m_pchData GetData()->nRefs++
If m_pchData had been == stringSrc.m_pchData, nothing at all happens.
So this bit of code is very fast:
void foo(CString strPassed)
{
}
CString str("Hello");
foo(str);
No string copy occurs, and no memory is allocated. A 32-bit value is pushed on the stack, that value is set (strPassed.m_pchData = str.m_pchData), and an integer is incremented (strPassed.GetData()->nRefs++). That's only one operation more than passing an int by value where: A 32-bit value is pushed on the stack, and that value is set. Now granted, it's definetly quite a few more assembly instructions, but that's why we have 500Mhz CPUs, so don't sweat cycles. When it comes to user interfaces, there's no reason to sweat CPU cycles, the computer is capable of executing billions of instructions in a time frame perceivable by a human. Obviously if your doing intensive graphics animation or massive quantities of data manipulation you might wanna look at your inner loops and optimize there.
The reason reference counts are kept is so that CString knows that it's "sharing" a string buffer with another CString object. If foo were to modify strPassed, CString would first allocate a new buffer and copy the string into that buffer (setting it's ref count to 1). Of course if foo never modifies strPassed, the allocation and copy never occur.
Empty Strings
An empty or uninitialized string m_pchData is set to _afxPchNil which looks like this:
-1 0 0 \0 (EOS)
---- ---- ---- - (_afxInitData)
^_afxPchNil
Note that a -1 ref count means that the string is "locked" and so modifying and empty string always results in a new allocation.
Epilogue
Anyhow, that's CString in a nutshell. It's really a fun class to dig into. So if you've ever worried about passing CString objects all over the place, remember that your really essentially only passing a pointer around. It's quite efficient and if you have need to manage dynamic structured data, you might even consider this model.
Please note that this information is accurate as of VC++ 6.0. I've heard that not all of this is true for previous versions of MFC, but I have not personally verified this.

Comments
Your Feet Will like Jordans Sneakers and relish the Encounter
Posted by NopFrufFElurl on 01/28/2013 02:31pmYour Toes Will cherish Jordans Sneakers and just like the Information Hearing one's physique is the critical excellent benefits take into account just about any athletics. In the event your toes are often crying inside the shoes or boots on account of distress, the chances are higher that you simply just aren't in a position to give your really finest effectiveness that day. As a result, to get inside of sports activities activities, furthermore for the sports activities skill and likewise skills, equally ingrained and designed, it is important to use the correct footwear. Uncover out much more about just how the very best shoe is admired because of your toes.? Ankle joint: The particular ankle joint props up finest bone from your ft * calcaneum. This can be truly the navicular bone which sports activities ths complete weight from the overall body just prior to switching the reasoning facing outward countrywide boundaries in the foot. The actual rearfoot is very vulnerable component and in addition the footwear must fit successfully with no firmly embracing the ankle joint. Since ankle joint incidents became typical inside athletics, the proper selection connected with sneakers may help in cutting these.? Center area of foot: Probably the most important the key toes comes from the particular ankle towards the commencing in the toes, that is inside the shape of the arc. Hence offering the camp for the ft improvement so it can help all through transfer of bodyweight with the ankle joint down from the exterior nationwide boundaries. The absolute maximum hugging from the shoes or boots will come about below and so the width on the place demands to get considered to be regarding experienceing the correct fitting.? Feet: The actual toes are incredibly sensitive along with essential parts. Normally shoes or boots limit since they achieve toes, thus causing the toes and fingers to swiftly pull towards the opposite. This may cause skin ailment along with other microbe infections within the webbing between each pair of toes and fingers.? Soles: A number of sporting functions individuals possess sweaty soles then the insoles from the shoes or boots must have the ability to take in the particular wetness formed.? Pores and skin: The skin knitwear likewise as launches sweat plus fatty create a variance, with due to the oil glands resulting in the toes for getting fatty. The knowledge can digest these matters together with commonly dry out speedily. Jordan really should be the favourate basketball player,one of the most genous basketball gamer,You will not at any time ignore this particular store,we provide the low cost jordans sneakers marketing on the net,cheap jordans basketball footwear at wholesale rates,inexpensive the nike jordan baseball shoes or boots for males, for girls,low cost nike jordan sneakers wholesale,and all kinds of sneakers are Totally free postage. G. [url=http://www.thoos.com/members/busooe/bio]jordans shoes for cheap[/url]| [url=http://universe3d.rc.fas.harvard.edu/wiki/index.php/User_talk:Lesher]kids air jordans[/url]|
ReplyJust thought about this when I woke up this morning...
Posted by Legacy on 08/05/2003 12:00amOriginally posted by: Leonhardt Wille
Hi there, nice article!
I have just one point to add:
The CString's equality operator is very uncomfortable...
I think that NO (absolutely NO) professional programmer compares two strings without making them lower! Okay, for some purpose you MAY do so (cheap pwd protection etc.)...
I just tried to override the CString provided by .NET, then I thought about downgrading to VC6 again... This ATL-**** sucks balls!
Please, if anyone has a nice CMyString class, please email me... I just wanted to get rid of this idea :D
regards
Replyleo
then someone should be able to explain this
Posted by Legacy on 05/08/2003 12:00amOriginally posted by: majoob
mk4vc60s_mfc.lib(CMk4DataContainer.obj) : error LNK2001: unresolved external symbol "char const * const _afxPchNil" (?_afxPchNil@@3PBDB)
ReplyAllocation question
Posted by Legacy on 12/17/2002 12:00amOriginally posted by: Larry Trussell
I have a question about heap usage with the CString class. The sample application is a debug build and the 64/128/... allocation buffers are not used. The buffer is allocated to the necessary size of the string. (BTW, the problem described below doesn't go away in the release build)
I have a test application (non-unicode) with a class containing an array of 40 CStrings. I then allocate 10,000 of those classes. When I look at the heap usage before and after this operation, there is a consumption of 4 bytes / string. That is what is expected.
Next, I set the value of each string to "A". Now my heap usage jumps up to 92 bytes / string! This exact same usage is seen for string values up to a 20 character string. At that point, usage jumps up to 108 bytes / string.
If I go into the test application and change the array of 40 CStrings to an array of 40 char[32], I see exactly 32 bytes per string in all cases with the test application.
Can you offer any suggestions as to why CStrings are consuming so much RAM?
Thanks,
LT
ReplyVery good article. Was helpful to me in debugging situation.
Posted by Legacy on 12/03/2002 12:00amOriginally posted by: JoeBrennan
I had a release-build library that yielded unresolved
Replyextern against my release task. No problem with debug-
build equivalents.
Since unresolved extern was _AfxPchNil I was able to
search on that term, find your article, and infer that
an uninitiliazed CString (which occurs only in the
library) was not being linked successfully to the
empty string Kahuna.
Life being short, I simply intialize the string
explicitly and problem gone. Thanks.
Converting CString to int
Posted by Legacy on 11/02/2001 12:00amOriginally posted by: Milk
Is there a way to Convert CStrings to Integers?
ReplyPassing CString by reference is faster
Posted by Legacy on 09/05/2001 12:00amOriginally posted by: Brangdon
Passing a CString by const reference will be faster, and take less code, than passing it by value.
This is mainly because the reference-counting code is out-of-line. (It is also fairly complex, with various tests for special cases etc.) Think about it: when you call:
void func( CString copy );
the compiler starts by calling the string's copy constructor, which is like:
CString::CString( const CString &rhs );
which necessarily passes by reference. So every pass by value has a pass by reference included. So it will be slower.
Reference counting means the difference isn't much. However, pass-by-const-reference is the norm for large objects. There is no reason to treat CString any differently to the norm. If you think pass-by-value is a worth-while optimisation, you're wrong: it's a pessimisation.
Reply
How to convert float to a CString?
Posted by Legacy on 08/07/2001 12:00amOriginally posted by: Henry Park
I'm trying to convert a float to a CString. I am using _fcvt(22.2, &decimal, &sign) to do the conversion. I plan to use the "decimal" value to place the "." in the proper string position.
ReplyCString in a Nutshell
Posted by Legacy on 07/11/2001 12:00amOriginally posted by: praveen nimbagiri
Excellent information about CString!
Well done douglas..
ReplySlightly Confused
Posted by Legacy on 07/06/2001 12:00amOriginally posted by: Ben Slavin
I was looking for information on the use of the CString class and how it works. I thought "CString in a Nutshell" to be a fitting title for a page with such information. How wrong I was.
This page provides practically no information on how one would start using CString. It doesn't even mention the include calls which need to be made to use it! I was disappointed upon seeing this, and am saddened that I was so misguided. I'd like to see a REAL explaination of CString as opposed to someone trying to simply show the usefulness of it.
Regards,
Reply--Ben
Loading, Please Wait ...