在C++中,使用字符串字面量初始化字符数组是一个好的实践吗?

5
在C++中,使用字符串初始化字符数组是一种好的做法吗? 例如:
char* abc = (char *) ("abcabc");

我在我的同事的代码中看到了很多这样的写法。我应该将它改为正确的做法吗? 例如:

std::string abc_str = "abcabc";
const char* abc= abc_str .c_str();

8
我没有看到一个字符数组。 - T.C.
12
@BufBills 嗯,这对我来说是个新闻。 - T.C.
10
我向您保证,@T.C.比您更有知识。 - jxh
4
你的第一个例子有问题,因为你在将一个字符串字面量的 const 属性去除。你的第二个例子也有问题,因为如果 abc_str 被修改了,那么 abc 可能指向无效的内存。 - Praetorian
3
侧记:请勿使用const字符串字面值,使用const char* s = hello"(非const已被弃用)。 - user2249683
显示剩余9条评论
3个回答

14

这个声明

char* abc = (char *) ("abcabc");

其实很糟糕。在C++中,字符串字面值的类型是常量字符数组。因此,有效的声明看起来应该像这样:

const char *abc = "abcabc";
注意:在 C 语言中,你确实可以编写
char *abc = "abcabc";

尽管字符串字面值是不可变的,但任何试图修改字符串字面值的行为都会导致未定义的行为。

顺便说一下,没有任何字符数组是由字符串字面值初始化的。:) 也许你指的是以下内容

char abc[] = "abcabc";

使用标准类std::string并不排除使用字符数组,甚至字符串字面量的指针。

请注意这些声明:

const char *abc = "abcabc";
and
std::string abc_str = "abcabc";
const char* abc= abc_str .c_str();

与第一个声明不同,字符串字面量具有静态存储期,并且它们的地址在程序执行期间不会改变。

在第二个声明中,指针abc指向可以被重新分配的动态分配内存,如果对象abc_str被更改,则指针将无效。

此外,第一个声明假定指针所指向的数组(字符串字面量)不会更改。在第二个声明中,假定std::string类型的对象将被更改。否则,声明std::string类型的对象而不是指针没有太大的意义。

因此,这些声明的含义是完全不同的。


7
char* abc = (char *) ("abcabc");

这样做是不好的,请勿这样操作。

您正在处理一个字符串字面量,它本应不可修改,但您却认为它可以被修改。

之后,

abc[0] = 'd';

编译器不会报错,但在运行时可能会出现问题。你需要使用如下语句:

char abc[] = "abcabc";

这将创建一个可修改的数组。

4

这两种情况都不好。

char* abc = (char*) ("abcabc");

字符串字面量是一个常量,因此可能存储在只读内存中。因此,对其进行写入可能会导致程序崩溃,这是未定义的行为。

与其取消const限定符,您应该保持它的const并复制一份,以便编辑其内容。

const char* abc = "abcabc";

另一个也应该避免使用:
std::string abc_str = "abcabc";
const char* abc = abc_str.c_str();

保持const是好的,但如果字符串被更改,它可能会被重新分配到内存中的另一个位置,导致指针悬空。
此外,在早期的C++11代码中,一旦分配指针,它就不再有效,因为没有保证它不是临时的。
最好每次调用abc_str.c_str()。
由于c_str()是如此微不足道的操作,编译器很可能会将其优化掉,使其与使用原始指针一样高效。
而你应该做的是始终使用std::string。如果您绝对需要一个const char*(用于旧的遗留代码),则可以使用c_str()获取它。
std::string abc_str = "abcabc"; // this is perfect why do more?

old_horrible_function(abc_str.c_str()); // only when needed

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