管理 CStringArray 条目
Managing CStringArray entries
这是在 Visual Studio MFC 应用程序的上下文中。
CStringArray::Add()
成员接受了一个 LPCTSTR
参数。如果我使用 CString
参数,我假设该参数被 CString
的 LPCTSTR
运算符隐式转换为 LPCTSTR
for Add()
,所以如果我有一个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()
return 之后,传递的参数超出范围并被删除。该数组是保存自己的副本,还是保存无效指针?
数据存储在 CStringArray
中只是一个指针,还是它实际上什至在调用 Add()
时创建了一个 CString
?
最后,如果我将 LPCTSTR
传递给添加,那么我假设如果我通过调用 new
来添加它来创建字符串,那么我肯定负责 delete
在 CStringArray
被销毁之前对它进行处理,对吗?
我只是不太明白 LPCTSTR
是如何在 CStringArray
中生存的,因为它只是一个本地字符串。
CStringArray
是一个MFC类型的数组,存放的是CString
的。如果使用 Unicode 编译,CString
是 CStringW
,如果使用 MBCS 编译,CString
是 CStringA
.
class 的要点是您不必为内存管理操心。它为你做。当您将 LPCTSTR
类型的字符串传递给数组时,它会构造一个 CString
对象并将其添加到数组中。当 CStringArray
对象超出范围时 and/or 它的析构函数被调用,它持有的所有 CString 都将被清理。
但是,有一个警告...
CString
class或多或少是引用计数。它有一个内部 class,因此当您复制 class 时,它不会复制所有数据。相反,它添加对某些内部结构的引用并使用它。如果你做了一些改变数据的操作,那么它就会从引用中分离出来并建立自己的新数据结构。您必须逐步执行代码才能看到这一点。
现在,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 转换为 non-const 字符串以调用 _tcsupr
时,我们违反了 const-ness(strupr
).由于 MFC 引用计数字符串的方式,“s”字符串内容也受到影响。在第二个分组调用 CString
的 MakeLower()
成员函数的情况下,只有那个特定的字符串受到影响。
这比你问的要多。也许对大家有帮助。
这是在 Visual Studio MFC 应用程序的上下文中。
CStringArray::Add()
成员接受了一个 LPCTSTR
参数。如果我使用 CString
参数,我假设该参数被 CString
的 LPCTSTR
运算符隐式转换为 LPCTSTR
for Add()
,所以如果我有一个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()
return 之后,传递的参数超出范围并被删除。该数组是保存自己的副本,还是保存无效指针?
数据存储在 CStringArray
中只是一个指针,还是它实际上什至在调用 Add()
时创建了一个 CString
?
最后,如果我将 LPCTSTR
传递给添加,那么我假设如果我通过调用 new
来添加它来创建字符串,那么我肯定负责 delete
在 CStringArray
被销毁之前对它进行处理,对吗?
我只是不太明白 LPCTSTR
是如何在 CStringArray
中生存的,因为它只是一个本地字符串。
CStringArray
是一个MFC类型的数组,存放的是CString
的。如果使用 Unicode 编译,CString
是 CStringW
,如果使用 MBCS 编译,CString
是 CStringA
.
class 的要点是您不必为内存管理操心。它为你做。当您将 LPCTSTR
类型的字符串传递给数组时,它会构造一个 CString
对象并将其添加到数组中。当 CStringArray
对象超出范围时 and/or 它的析构函数被调用,它持有的所有 CString 都将被清理。
但是,有一个警告...
CString
class或多或少是引用计数。它有一个内部 class,因此当您复制 class 时,它不会复制所有数据。相反,它添加对某些内部结构的引用并使用它。如果你做了一些改变数据的操作,那么它就会从引用中分离出来并建立自己的新数据结构。您必须逐步执行代码才能看到这一点。
现在,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 转换为 non-const 字符串以调用 _tcsupr
时,我们违反了 const-ness(strupr
).由于 MFC 引用计数字符串的方式,“s”字符串内容也受到影响。在第二个分组调用 CString
的 MakeLower()
成员函数的情况下,只有那个特定的字符串受到影响。
这比你问的要多。也许对大家有帮助。