Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
管理CStringArray条目_String_Mfc - Fatal编程技术网

管理CStringArray条目

管理CStringArray条目,string,mfc,String,Mfc,这是在VisualStudioMFC应用程序的上下文中 CStringArray::Add()成员接受一个LPCTSTR参数。如果我使用CString参数,我假定CString的LPCTSTR操作符将Add()的CString参数隐式转换为LPCTSTR,因此如果我有CStringArray arr和CString s并调用arr.Add(s),这与调用arr.Add((LPCTSTR)s)完全相同,对吗 所以,当调用Add()时,CStringArray是简单地存储传递的指针,还是单独复制字符

这是在VisualStudioMFC应用程序的上下文中

CStringArray::Add()
成员接受一个
LPCTSTR
参数。如果我使用
CString
参数,我假定
CString
LPCTSTR
操作符将
Add()
CString
参数隐式转换为
LPCTSTR
,因此如果我有
CStringArray arr
CString s
并调用
arr.Add(s)
,这与调用
arr.Add((LPCTSTR)s)
完全相同,对吗

所以,当调用
Add()
时,
CStringArray
是简单地存储传递的指针,还是单独复制字符串并存储它?我这样问是因为我想知道在添加字符串时是否必须创建一个持久字符串,或者在添加后是否可以删除我的字符串。例如,以下哪项是正确的

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
中存储的数据只是一个指针,还是在调用
Add()
时,它实际上甚至创建了一个
CString

最后,如果我将
LPCTSTR
传递给add,那么我假设如果我通过调用
new
来创建字符串来添加它,那么我肯定要负责
delete
CStringArray
被销毁之前将其删除,对吗


我只是不太明白当它只是一个本地字符串时,
LPCTSTR
如何在
CStringArray
中生存。

CStringArray
是一个存储C
字符串的MFC类型数组。如果使用Unicode编译,
CString
是一个
CStringW
,如果为MBCS编译,
CString
是一个
CStringA

本课程的重点是,您不必太担心内存管理。它是为你做的。将
LPCTSTR
类型字符串传递给数组时,它将构造一个
CString
对象并将其添加到数组中。当
CStringArray
对象超出范围和/或调用其析构函数时,它所持有的所有cstring都将被清除

然而,有一个警告

CString
类是或多或少计数的引用。它有一个内部类,当你复制一个类时,它不会复制所有的数据。相反,它添加了对一些内部结构的引用并使用它。如果您执行了一些更改数据的操作,那么它会将自身与引用分离,并设置自己的新数据结构。您必须单步通过代码才能看到这一点

现在,
CStringArray
有两个
Add()
方法。一个接受一个
LPCTSTR
另一个接受一个c
onst CString&
。第二个复制了
CString
,进行上一段中提到的准参考计数

这只是补充信息。使用
CStringArray
,您真的不必过于担心内存管理问题。它为你做了繁重的工作

你唯一需要担心的是引用计数,如果你做了一些愚蠢的事情而忽略了常量

考虑以下代码:

#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"

}
#包括
#包括
void main()
{
CString s(“这是我的字符串\n”);
CStringArray;
sArray。添加(s);
sArray。添加(s);
_tprintf((LPCTSTR)s);/“这是我的字符串”
_tprintf((LPCTSTR)sArray[0]);/“这是我的字符串”
_tprintf((LPCTSTR)sArray[1]);/“这是我的字符串”
sArray[0]。MakeLower();
_tprintf((LPCTSTR)s);/“这是我的字符串”
_tprintf((LPCTSTR)sArray[0]);/“这是我的字符串”
_tprintf((LPCTSTR)sArray[1]);/“这是我的字符串”
LPCTSTR lpsz=sArray[1];
_tcsupr((LPTSTR)lpsz);//不要这样做!!!,也会更改s!!!
_tprintf((LPCTSTR)s);/“这是我的字符串”
_tprintf((LPCTSTR)sArray[0]);/“这是我的字符串”
_tprintf((LPCTSTR)sArray[1]);/“这是我的字符串”
}
如果您查看第三个分组的打印输出,您会发现当我们为调用
\u tcsupr
strupr
)将lpsz强制转换为非常量字符串时,违反了常量。由于MFC引用计数字符串的方式,“s”字符串内容也会受到影响。在第二个分组调用
CString
MakeLower()
成员函数的情况下,只有该特定字符串有效


这比你要求的要多。也许这对人们会有帮助。

为什么不调试Add调用?这将带您了解源代码。@AndrewTruckle:我不知道源代码是可用的。我以为它只是一个库。如果你使用调试模式,那么它将进入源文件。@AndrewTruckle:好的,非常好。我看到它最终使用
memcpy()
创建参数所指向字符串的私有副本。这就回答了所有问题,谢谢+调试配置并不是进入MFC源代码的严格要求。MFC版本的Microsoft host debug symbols也构建在它们的公共符号服务器上。
CStringT
类模板有一个专用接口,用于修改和更新内部字符缓冲区(
GetBuffer()
和friends)。如果您在其规范之外使用
CStringT
,则一切都会发生。因为没有明显的理由这么做,所以解决办法很简单:不要。我不得不在一位同事离开后修复他工作中的一个bug。他抛弃了字符串的常量,将其传递给一个采用LPTSTR的API…你知道什么…它引入了一个bug…令人震惊,对吗?