这是在 Visual Studio MFC 应用程序的上下文中。
CStringArray::Add()
成员(member)需要 LPCTSTR
争论。如果我使用 CString
参数,我认为该参数被隐式转换为 LPCTSTR
对于 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
添加,那么我假设如果我通过调用 new
创建字符串添加它,那么我肯定要对 delete
负责在 CStringArray
之前查看它被毁了,对吧?
我只是不太明白 LPCTSTR
是如何做到的能够生存在CStringArray
当它只是一个本地字符串时。
最佳答案
CStringArray
是存储 CString
的 MFC 类型数组。如果使用 Unicode 进行编译,则 CString
是 CStringW
;如果使用 MBCS 进行编译,则 CString
是 CStringA
>.
该类(class)的重点是您不必太担心内存管理。它为你做这件事。当您将 LPCTSTR
类型字符串传递给数组时,它会构造一个 CString
对象并将其添加到数组中。当 CStringArray 对象超出范围和/或其析构函数被调用时,它所持有的所有 CString 都将被清除。
但是,有一个警告......
CString
类或多或少都有引用计数。它有一个内部类,因此当您复制一个类时,它不会复制所有数据。相反,它添加了对某些内部结构的引用并使用它。如果您执行某些更改数据的操作,那么它会将自身与引用分离并设置自己的新数据结构。您必须单步执行代码才能看到这一点。
现在,CStringArray
有两个 Add()
方法。一个采用 LPCTSTR
,另一个采用 const 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
)。由于 MFC 对字符串进行引用计数的方式,“s”字符串内容也会受到影响。在第二个分组调用 CString
的 MakeLower()
成员函数的情况下,只有该特定字符串受到影响。
这比你要求的还要多。也许这会对人们有所帮助。
关于string - 管理 CStringArray 条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64013353/