C++不推荐将字符串常量转换为'char*'

mka*_*han 144 c++ string explicit-constructor

我有一个班级 private char str[256];

为此,我有一个显式的构造函数:

explicit myClass(const char *func)
{
    strcpy(str,func);
}
Run Code Online (Sandbox Code Playgroud)

我称之为:

myClass obj("example");
Run Code Online (Sandbox Code Playgroud)

当我编译这个时,我得到以下警告:

不推荐将字符串常量转换为'char*'

为什么会这样?

fni*_*eto 144

警告:

不推荐将字符串常量转换为'char*'

是因为你在某处(不是在你发布的代码中)做的事情是这样的:

void foo(char* str);
foo("hello");
Run Code Online (Sandbox Code Playgroud)

问题是您正在尝试将字符串文字(带有类型const char[])转换为char*.

你可以将a转换const char[]const char*因为数组衰减到指针,但你正在做的是使一个可变的常量.

这种转换可能允许C兼容性,只是给你提到的警告.


sel*_*tze 131

这是您遇到以下情况时看到的错误消息:

char* pointer_to_nonconst = "string literal";
Run Code Online (Sandbox Code Playgroud)

为什么?那么,C和C++在字符串文字的类型上有所不同.在C中,类型是char数组,在C++中,它是char的常量数组.在任何情况下,都不允许更改字符串文字的字符,因此C++中的const实际上不是限制,而是更多类型安全的东西.从A转换const char*char*一般也不是没有可能的明确的转换出于安全原因.但是为了向后兼容C,语言C++仍然允许为a分配字符串文字,char*并为您提供有关不推荐使用此转换的警告.

所以,你const在程序中缺少一个或多个s表示const正确性.但是,您向我们展示的代码不是问题,因为它不会执行此类不推荐的转换.警告必须来自其他地方.

  • 不幸的是,考虑到对这个问题的观点和投票,OP从未提供实际证明问题的代码. (16认同)
  • 您可以通过从 `MyClass` 构造函数中删除 `const` 来重现 OP 代码的问题......然后你可以通过添加回 `const` 来修复它。 (2认同)

sac*_*tiw 90

作为答案否.2由fnieto - Fernando Nieto清楚而正确地描述了这个警告是因为你正在做的代码中的某个地方(不是你发布的代码中):

void foo(char* str);
foo("hello");
Run Code Online (Sandbox Code Playgroud)

但是,如果您希望保持代码无警告,则只需对代码进行相应更改:

void foo(char* str);
foo((char *)"hello");
Run Code Online (Sandbox Code Playgroud)

也就是说,简单地将string常量强制转换为(char *).

  • 或者,创建函数:void foo(const char*str) (13认同)
  • @Caprooja是的,声明param为'指向常量的指针'也适用于这种情况.但是通过此更改,用户无法使用用户可能在实现部分中执行的"str"指针更改/重新分配存储在地址中的值.所以这是你可能想要注意的事情. (3认同)

ani*_*bey 35

有3种解决方案:

解决方案1:

const char *x = "foo bar";
Run Code Online (Sandbox Code Playgroud)

解决方案2:

char *x = (char *)"foo bar";
Run Code Online (Sandbox Code Playgroud)

解决方案3:

char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");
Run Code Online (Sandbox Code Playgroud)

也可以使用数组代替指针,因为数组已经是常量指针.

  • 对于解决方案3,有"strdup".与您的代码不同,它将为终止NUL字符分配空间,而不会超出分配范围. (6认同)
  • 您是否会将评论整合到您的答案中?解决方案3仍然是危险的错误. (3认同)
  • 应避免使用解决方案2. (2认同)

Sah*_*ngh 5

出现此问题的原因(比其他人已经解释的问题更难检测char* str = "some string")是当您使用constexpr.

\n\n
constexpr char* str = "some string";\n
Run Code Online (Sandbox Code Playgroud)\n\n

看起来它的行为类似于const char* str,因此不会像之前发生的那样引起警告,char*但它的行为却与 一样char* const str

\n\n

细节

\n\n

常量指针,以及指向常量的指针。const char* str、 和之间的区别char* const str可以解释如下。

\n\n
    \n
  1. const char* str:将 str 声明为指向 const char 的指针。这意味着该指针指向的数据是恒定的。可以修改指针,但任何修改数据的尝试都会引发编译错误。\n\n
      \n
    1. str++ ;有效的。我们正在修改指针,而不是所指向的数据。
    2. \n
    3. *str = \'a\';无效的。我们正在尝试修改所指向的数据。
    4. \n
  2. \n
  3. char* const str:声明 str 为指向 char 的 const 指针。这意味着该点现在是恒定的,但所指向的数据也不是恒定的。指针无法修改,但我们可以使用指针修改数据。\n\n
      \n
    1. str++ ;无效的。我们正在尝试修改指针变量,它是一个常量。
    2. \n
    3. *str = \'a\';有效的。我们正在尝试修改所指向的数据。在我们的例子中,这不会导致编译错误,但会导致运行时错误,因为该字符串很可能会进入已编译二进制文件的只读部分。如果我们有动态分配的内存,那么这个语句就有意义,例如。char* const str = new char[5];
    4. \n
  4. \n
  5. const char* const str:将 str 声明为指向 const char 的 const 指针。在这种情况下,我们既不能修改指针,也不能修改所指向的数据。\n\n
      \n
    1. str++ ;无效的。我们正在尝试修改指针变量,它是一个常量。
    2. \n
    3. *str = \'a\';无效的。我们试图修改这个指针所指向的数据,它也是常量。
    4. \n
  6. \n
\n\n

就我而言,问题是我期望constexpr char* str表现得像const char* str,而不是char* const str,因为从视觉上看它似乎更接近前者。

\n\n

此外,生成的警告与constexpr char* str = "some string"略有不同char* str = "some string"

\n\n
    \n
  1. 编译器警告constexpr char* str = "some string"ISO C++11 does not allow conversion from string literal to \'char *const\'
  2. \n
  3. 编译器警告char* str = "some string"ISO C++11 does not allow conversion from string literal to \'char *\'.
  4. \n
\n\n

提示

\n\n

您可以使用C 乱码 \xe2\x86\x94 英语转换器C声明转换为易于理解的英语语句,反之亦然。这是C唯一的工具,因此不会支持C++.

\n