不推荐从字符串 const 转换。到 wchar_t*
Posted
技术标签:
【中文标题】不推荐从字符串 const 转换。到 wchar_t*【英文标题】:Deprecated conversion from string const. to wchar_t* 【发布时间】:2011-04-16 07:31:33 【问题描述】:您好,我有一个泵类,它需要使用一个成员变量,该变量是指向包含端口地址的 wchar_t 数组的指针,即:“com9”。
问题是当我在构造函数中初始化这个变量时,我的编译器会标记一个折旧的转换警告。
pump::pump()
this->portNumber = L"com9";
这工作正常,但每次我编译时的警告都很烦人,让我觉得我做错了什么。
我尝试创建一个数组,然后像这样设置成员变量:
pump::pump()
wchar_t port[] = L"com9";
this->portNumber = port;
但由于某种原因,这使我的 portNumber 指向“F”。
显然是我的另一个概念问题。
感谢您对我的愚蠢问题的帮助。
编辑:
根据要求,portNumber 的定义是:
class pump
private:
wchar_t* portNumber;
感谢答案,现在已更改为:
class pump
private:
const wchar_t* portNumber;
【问题讨论】:
请告诉我们pump::portNumber
的定义。
【参考方案1】:
如果portNumber
是wchar_t*
,它应该是const wchar_t*
。
字符串字面量是不可变的,所以元素是const
。存在从字符串文字到非常量指针的不推荐转换,但这很危险。进行更改以保持类型安全,而不是使用不安全的转换。
第二个失败是因为你指向了一个局部变量的内容。当构造函数完成时,变量消失并且你指向一个无效的位置。使用它会导致未定义的行为。
最后,使用初始化列表:
pump::pump() :
portNumber(L"com9")
初始化列表是初始化,构造函数是完成构造。 (另外,this->
对几乎所有 C++ 人来说都是丑陋的;它既不好也不多余。)
【讨论】:
如果 portNumber 的定义因为它是 3rd 方代码的一部分而无法更改怎么办?无论我尝试什么,我似乎都无法让警告消失,因为我不知道如何告诉编译器不要制作文字。 @MikeVersteeg:如果您无法更改代码,您唯一的选择是尝试抑制警告。 AFAIK,大多数编译器都有使用编译指示禁用和重新启用警告的方法 - 您可以在#include
之前禁用警告,然后重新启用。
谢谢,但是对于 C++11 编译器(至少不是我的),这不再可能。我确实设法通过动态创建一个字符串并使用它来解决这个问题。从这篇文章中学到了很多东西。【参考方案2】:
使用const wchar_t*
指向文字。
存在转换的原因是因为从早期版本的 C 开始,将字符串文字分配给非常量指针 [*] 是有效的。不推荐使用它的原因是修改文字是无效的,并且使用非常量指针来引用不能修改的东西是有风险的。
[*] C 最初没有const
。当添加const
时,显然它应该适用于字符串文字,但已经有代码在const
存在之前编写,如果突然你不得不到处撒const
,那将会中断。我们今天仍在为语言的这一重大变化付出代价。由于您使用的是 C++,因此对这种语言甚至没有什么重大改变。
【讨论】:
毁掉大多数 C++ 的一件事是 C 的向后兼容性,即使在最愚蠢的选择(包括 C 标准库)中也是如此。【参考方案3】:显然,portNumber
是 wchar_t *
(非常量),对吗?如果是这样:
第一个是错误的,因为字符串字面量是只读的(它们是指向存储在可执行文件字符串表中的 char 数组的常量指针通常,映射到内存某处,通常在只读页面中)。
IIRC 批准了到非常量 char
s/wchar_t
s 的丑陋隐式转换,以实现与 const
甚至不存在时编写的旧代码的兼容性;可悲的是,它让许多不知道 const 正确性 意味着什么的白痴摆脱了编写询问非 const 指针的代码,即使 const 指针是正确的选择。
第二个是错误的,因为你让portNumber
指向一个分配在堆栈上的变量,当构造函数返回时该变量被删除。构造函数返回后,portNumber
中存储的指针指向随机垃圾。
如果不需要修改,正确的做法是将portNumber
声明为const wchar_t *
。相反,如果它确实需要在类的生命周期内进行修改,通常最好的方法是完全避免使用 C 样式的字符串,而只需输入 std::wstring
,这会很小心与字符串相关的所有簿记。
【讨论】:
感谢您的信息。在这种情况下,端口号可能会动态更改(从下拉菜单中),因为泵可能并不总是在 com9 上。我完全使用 wchar_t 指针的原因是因为它需要作为 CreateFile() 函数中的参数。我会看看它是否接受 std::wstring。 它不接受 wstring,但 wstring(作为任何基于 std::basic_string 构建的字符串)提供了 c_str() 方法,该方法返回一个 const wchar_t * 以让 C 函数访问其内容。以上是关于不推荐从字符串 const 转换。到 wchar_t*的主要内容,如果未能解决你的问题,请参考以下文章
我想将std :: string转换为const wchar_t *
错误 C2440:“默认参数”:无法从“const wchar_t [1]”转换为“BSTR”