从string const转换为wchar_t*已被弃用

7

你好,我有一个泵类需要使用指向包含端口地址(例如:“com9”)的wchar_t数组的成员变量指针。

问题在于,当我在构造函数中初始化此变量时,我的编译器会出现过时转换警告。

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 的定义。 - Maciej Hehl
3个回答

13
如果portNumberwchar_t*,它应该是一个const wchar_t*
字符串字面值是不可变的,因此其元素都是const类型。虽然存在一种已弃用的从字符串字面值到非const指针的转换,但这是很危险的。所以修改要保持类型安全且不使用不安全的转换。
第二个例子失败的原因是你指向了局部变量的内容。当构造函数完成时,该变量将消失,您将指向无效位置。使用它会导致未定义行为。
最后需要使用初始化列表:
pump::pump() :
portNumber(L"com9")
{}

初始化列表用于初始化,构造函数用于完成构造过程。(此外,this->对于几乎所有C++开发者来说都很丑陋;它不够优雅也是多余的。)


如果端口号的定义不能更改,因为它是第三方代码的一部分怎么办?无论我尝试什么,似乎都无法消除警告,因为我不知道如何告诉编译器不要生成文字。 - Mike Versteeg
@MikeVersteeg:如果你不能改变代码,那么你唯一的选择就是尝试抑制警告。据我所知,大多数编译器都有通过#pragma禁用和重新启用警告的方法——你可以在#include之前禁用警告,并在之后重新启用。 - GManNickG
谢谢,但是使用C++11编译器已经不再可能了(至少我的不能)。我设法通过动态创建一个字符串并使用它来解决这个问题。从这篇文章中学到了很多东西。 - Mike Versteeg

2
使用const wchar_t*指向字面值。
这种转换的原因是因为从早期版本的C语言开始,将字符串字面值分配给非const指针是有效的。它被弃用的原因是修改字面值是无效的,并且使用非const指针引用不能被修改的内容是有风险的。
C语言最初没有const关键字。当const被添加时,显然应该将其应用于字符串字面值,但是已经存在了在const不存在之前编写的代码,如果突然必须到处添加const,则会破坏该代码。即使在今天,我们仍在为这种对语言的破坏性更改付出代价。由于您正在使用的是C++,所以这甚至不是对该语言的破坏性更改。

C++ 中破坏代码质量的一个因素是其与 C 的向后兼容,即使在一些愚蠢的选择中也保留了这种兼容性(包括 C 标准库)。 - Matteo Italia

1

显然,portNumber 是一个非常量的 wchar_t *,对吗?如果是这样的话:

  • 第一个是错误的,因为字符串字面值是只读的(它们是指向 char 数组的常量指针,通常存储在可执行文件的字符串表中,该表被映射到内存中的某个位置,通常在只读页面中)。
    难看的、隐式的转换成非常量的 chars/wchar_ts 被批准,我记得,是为了与旧代码兼容,当时甚至不存在 const;不幸的是,它让很多不知道什么是 const 正确性 的白痴得以编写请求非常量指针的代码,即使 const 指针才是正确的选择。

  • 第二个是错误的,因为你让 portNumber 指向在堆栈上分配的变量,该变量在构造函数返回时被删除。构造函数返回后,存储在 portNumber 中的指针指向随机垃圾。

正确的方法是,如果不需要修改,则将 portNumber 声明为 const wchar_t *。如果在类的生命周期内确实需要修改它,则通常最好的方法是避免使用C风格字符串,而只需添加一个 std :: wstring ,它会处理与字符串相关的所有簿记。

感谢您提供的信息。在这种情况下,端口号可能会动态更改(从下拉菜单中),因为泵可能并不总是在com9上运行。我使用wchar_t指针的原因是因为在CreateFile()函数中需要它作为参数。我会尝试看看它是否接受std::wstring。 - Zac
1
它不接受wstring,但是wstring(作为任何基于std :: basic_string构建的字符串)提供了c_str()方法,返回const wchar_t *以让C函数访问其内容。 - Matteo Italia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接