2013-01-16 31 views
3

有谁根据this site知道为什么这个代码是不正确的:为什么在使用可变参数函数时必须将CString强制转换为LPCSTR?

CString First("John"); 
CString Last("Doe"); 

CString Name; 

Name.Format("%s %s", First, Last); // Name may be garbage text 

Name.Format("%s %s", (LPCSTR)First, (LPCSTR)Last); // this is the correct way 

CString::Format微软文档中说:

...当你传递一个字符串作为可选参数,你必须明确地将其作为LPCTSTR投...

我总是使用“错误”的方式(没有LPCSTR转换),我从来没有遇到过问题。

我失去了一些东西在这里?

+0

关于此的有趣链接是[这里](https://groups.google.com/forum/?fromgroups#!topic/microsoft.public.vc.mfc/Ao-A8D1-JT0)和[here](http ://stackoverflow.com/questions/922603/should-i-cast-a-cstring-passed-to-format-printf-and-varargs-in-general/924635#924635)。 –

回答

3

因为没有Format函数的内部完成投就像有是当你如果你写printf("%d", a);没有投做是为了a因为printf的假设%d已经告诉指定的参数printf()

没有投做什么数据类型a是。

为了确保CString转换为LPCSTR即你需要转换,这将调用操作员对返回LPCSTRCString参数%s。在CString的后续版本中,字符串被存储起来,这样当你没有进行强制转换时,它仍然会被打印为LPCSTR,但要确保最好进行强制转换。

或者以另一种方式:当一个可变参数函数经过的参数,它使用的格式说明知道的参数的大小,如果格式说明符不符合你的垃圾的论点。由于CString没有格式说明符,因此需要将CString转换为LPCSTR。

顺便说一句,你应该在C++

2

投射到LPCSTR使用static_cast<LPCSTR>(First), static_cast<LPCSTR>(Last)调用转换运算符operator LPCSTR()(应该是operator const char *()

不调用LPCSTR意味着要传递的整个CString对象然后盲目地使用第一32或下面的结构作为一个字符指针64个比特

总括:LPCSTR(str)被调用一个方法,以确保正确的行为,而str是盲位操作

+0

这实际上是发生了什么。如果你把一个CString对象作为一个可变参数,编译器实际上将CString对象的32个第一位压入栈中。这在CString的情况下工作,因为CString类的设计方式是任何CString对象的32位是指向实际字符串的指针。 –

+1

@MichaelWalz:你说的是,你对你的代码是未定义的行为感到满意,并且取决于'CString'的实现细节,可能或不会改变,因为在你的特定情况下它似乎工作。现在你的问题是*你为什么要施放?*并且答案很简单,以避免未定义的行为。 –

+0

@DavidRodríguez-dribeas,我没有说我很高兴,我只是说了究竟在做什么。但是,如果CString类的布局改变,那么肯定使用一个强制转换将节省你的一天。 –

1

我认为(对不起,我没有MFC现在可用于检查)所需要只是为了效率原因,投,以避免无用的临时副本MFC必须做的时候如果参数类型未知(CString的是懒洋洋地复制在修改)。

它是CString的存储器分配保留空间诀窍之前this为比缓冲液(TCHAR *),如参考计数器其它一些必要的数据。

然后,当您通过值传递一个CString到一个可变参数函数时,它'看到'缓冲区(一个指针) 强制转换'只提取'缓冲区,而不调用复制构造函数。

+1

实际上,当这种对象作为可变参数传递时,并没有创建临时CString对象。在前面的答案中查看我的评论。 –

+0

@MichaelWalz:我在重新思考:应该有一个调用来拷贝构造函数(通过值传递的参数),但是由于'copy on modify',没有缓冲区拷贝。 – CapelliC

+0

仅供参考:当您不使用演员时,不会调用复制构造函数。当你使用转换时,调用操作符被调用,但不复制构造函数。请参阅以上Jeffery Thomas的回答。 –

1

因为如果您使用子分类的CString参数它会中断。

+0

使用微软编译器,即使你继承了CString,它仍然继续工作,但如果CString包含虚函数,那么你会得到垃圾,因为在这种情况下,前4个字节是nomore指向字符串的指针,但是指向虚函数表的指针。 –

+0

完全解释它!不幸的是,我所有的dervied CString类都使用虚拟析构函数进行清理。我不确定我可以用非虚拟析构函数逃脱。我不使用CString * ptr = new CMyStringEx(),但另一个程序员可能有。 –

相关问题