问题描述
这是在Visual Studio MFC应用程序的上下文中。
CStringArray::Add()
成员接受一个LPCTSTR
参数。如果我使用CString
参数,则假定LPCTSTR
的{{1}}运算符将Add()
的参数隐式转换为LPCTSTR
,所以如果我有一个CString
和CStringArray arr
然后呼叫CString s
,这与呼叫arr.Add(s)
完全相同,对吧?
因此,在调用arr.Add((LPCTSTR)s)
时,Add()
是简单地存储传递的指针,还是对字符串进行单独的复制并存储呢?我问是因为我想知道添加字符串时是否必须创建一个持久字符串,或者添加字符串后是否可以删除该字符串。例如,在以下情况中,如果CStringArray
,foo1()
或foo2()
中的任何一个是正确的?
foo3()
让我担心的是,在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); }
...
};
和foo1()
返回之后,传递的参数超出范围并被删除。然后,该数组保存自己的副本,还是保存无效的指针?
存储在foo2()
中的数据仅仅是一个指针,还是实际上甚至可以在调用CStringArray
时创建一个CString
?
最后,如果我要传递Add()
进行添加,那么我假设如果我通过调用LPCTSTR
来创建字符串以添加字符串,那么我肯定要对{{1 }}在new
被销毁之前将其删除,对吗?
当只是一个本地字符串时,我只是不太了解delete
在CStringArray
中如何生存。
解决方法
CStringArray
是一个存储C String
的MFC类型数组。如果使用Unicode进行编译,则CString
是CStringW
;如果使用MBCS进行编译,则CString
是CStringA
。
该类的重点是您不必太担心内存管理。它为你做。当您将LPCTSTR
类型的字符串传递给数组时,它将构造一个CString
对象并将其添加到数组中。当CStringArray
对象超出范围和/或调用其析构函数时,将清除其持有的所有CString。
但是,有一个警告...
CString
类或多或少地被引用计数。它具有一个内部类,这样当您复制一个类时,它不会复制所有数据。相反,它添加了对一些内部结构的引用并使用了它。如果您执行某些更改数据的操作,则它会与引用分离,并建立自己的新数据结构。您必须单步执行代码才能看到这一点。
现在,CStringArray
有两个Add()
方法。一个取LPCTSTR
,另一个取c onst CString&
。第二个副本是CString
的副本,它进行了上一段中提到的准引用计数。
那只是添加的信息。您真的不需要担心使用CStringArray
来进行内存管理。它为您完成了繁重的工作。
您唯一需要担心CString
引用计数的地方就是您是否做过愚蠢的事情而忽略了const。
考虑以下代码:
#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"
}
如果查看第三组的打印输出,则会发现在将lpsz强制转换为非常量字符串以调用_tcsupr
(strupr
)时,我们违反了const-ness。由于MFC引用对字符串进行计数的方式,“ s”字符串的内容也受到影响。在第二个分组调用MakeLower()
的{{1}}成员函数的情况下,仅该特定字符串有效。
这超出了您的要求。也许会对人们有所帮助。