Reputation: 351
This is in the context of a Visual Studio MFC application.
The CStringArray::Add()
member takes an LPCTSTR
argument. If I use a CString
argument, I presume the argument is implicitly converted to LPCTSTR
for Add()
by the LPCTSTR
operator of CString
, so if I have a CStringArray arr
and a CString s
and call arr.Add(s)
, this is exactly the same as calling arr.Add((LPCTSTR)s)
, right?
So when Add()
is called, does CStringArray
simply store the passed pointer, or does it make a separate copy of the the string and store that? I'm asking because I wonder if I have to make a persistent string when I add it, or if my string can be deleted after it is added. For example, which if any of foo1()
, foo2()
, or foo3()
is correct in the following?
class MyClass :
{
...
CStringArray arr;
CString mystr;
void foo1() { arr.Add(_T("Bippety")); }
void foo2() { CString s(_T("Boppety"); arr.Add(s); }
void foo3() { mystr = _T("Boop"); arr.Add(mystr); }
...
};
The thing that worries me is that after foo1()
and foo2()
return, the passed argument goes out of scope and is deleted. Does the array then hold its own copy, or does it hold an invalid pointer?
Is the data stored in the CStringArray
as just a pointer, or does it actually even go so far as to create a CString
when Add()
is called?
Finally, if I'm passing LPCTSTR
to add, then I assume that if I created the string by a call to new
to add it, then I'm surely responsible for delete
ing it before CStringArray
is destroyed, right?
I just can't quite see how the LPCTSTR
can survive in the CStringArray
when it's only a local string.
Upvotes: 2
Views: 1529
Reputation: 6050
CStringArray
is an MFC type array that stores CString
's. If you compile with Unicode, the CString
is a CStringW
and if you compile for MBCS, the CString
is a CStringA
.
The point of the class is that you do not have to worry so much about memory management. It does it for you. When you pass an LPCTSTR
type string to the array, it constructs a CString
object and adds it to the array. When the CStringArray
object goes out of scope and/or its destructor gets called, all the CStrings it is holding onto will be cleaned up.
However, there is a caveat...
The CString
class is reference counted more or less. It has an internal class such that when you make a copy of a class, it doesn't copy all of the data. Instead, it adds a reference to some of the internal structures and uses that. If you do some operation that changes the data, then it detaches itself from the reference and sets up its own new data structures. You have to step through the code to see this.
Now, the CStringArray
has two Add()
methods. One takes an LPCTSTR
the other a const CString&
. The second one makes a copy of CString
doing the quasi reference counting mentioned in the previous paragraph.
That is just added information. You really don't need to worry about memory management too hard with the CStringArray
. It does the heavy lifting for you.
The only part where you have to worry about CString
reference counting is if you do stupid stuff and ignore const.
Consider the following code:
#include <afx.h>
#include <stdio.h>
void main()
{
CString s("HERE is my string\n");
CStringArray sArray;
sArray.Add(s);
sArray.Add(s);
_tprintf((LPCTSTR) s); // "HERE is my string"
_tprintf((LPCTSTR) sArray[0]); // "HERE is my string"
_tprintf((LPCTSTR) sArray[1]); // "HERE is my string"
sArray[0].MakeLower();
_tprintf((LPCTSTR) s); // "HERE is my string"
_tprintf((LPCTSTR) sArray[0]); // "here is my string"
_tprintf((LPCTSTR) sArray[1]); // "HERE is my string"
LPCTSTR lpsz = sArray[1];
_tcsupr((LPTSTR) lpsz); // don't do it!!!, also changes s!!!
_tprintf((LPCTSTR) s); // "HERE IS MY STRING"
_tprintf((LPCTSTR) sArray[0]); // "here is my string"
_tprintf((LPCTSTR) sArray[1]); // "HERE IS MY STRING"
}
If you look at the printout from the third grouping, you see that we violated const-ness when we cast lpsz to a non-const string for the call to _tcsupr
(strupr
). Because of the way MFC reference counts strings, the "s" string contents were also effected. In the case of the second grouping calling the MakeLower()
member function of CString
, only that particular string was effected.
This is more than you asked. Maybe it will be helpful to people.
Upvotes: 3