何时使用const char *,何时使用const char[]
When to use const char * and when to use const char []
我知道它们是不同的,我知道它们是如何不同的,我阅读了所有我能找到的关于char*
和char[]
的问题
但是所有这些答案都没有告诉我们什么时候应该使用它们。
我的问题是:
什么时候使用
const char *text = "text";
和什么时候使用
const char text[] = "text";
有什么指导方针或规则吗?
举个例子,哪个更好:
void withPointer()
{
const char *sz = "hello";
std::cout << sz << std::endl;
}
void withArray()
{
const char sz[] = "hello";
std::cout << sz << std::endl;
}
(我知道std::string
也是一个选项,但我特别想知道char
指针/数组)
两者都明显不同,首先:
- 第一个创建一个指针。
- 第二行创建一个数组。
请继续阅读以获得更详细的解释:
数组版本:
char text[] = "text";
创建一个足够大的数组来容纳字符串字面值"text",包括它的NULL
终止符。数组text
初始化为字符串字面值"text"。数组可以在以后修改。此外,即使在编译时也知道数组的大小,因此可以使用 sizeof
操作符来确定它的大小。
指针版本:
char *text = "text";
创建一个指向字符串文本"text"的指针。这比数组版本快,但是指针指向的字符串不应该被改变,因为它位于只读实现定义的内存中。修改这样的字符串字面值会导致未定义行为。
实际上c++ 03不赞成使用没有const
关键字的字符串字量。所以声明应该是:
const char*text = "text";
此外,需要使用strlen()
函数,而不是sizeof
来查找字符串的大小,因为sizeof
操作符只会给您指针变量的大小。
哪个版本更好?
取决于用法。
- 如果您不需要对字符串进行任何更改,则使用指针版本。
- 如果你想改变数据,使用数组版本。
编辑:我刚刚注意到(在评论中),OP寻求以下之间的区别:
const char text[]
和const char* text
除了关于修改字符串字面值的问题,上面的不同点仍然适用。有了const
限定符,数组test
现在是一个包含const char
类型元素的数组,这意味着它们不能被修改。
考虑到这一点,我会选择数组版本而不是指针版本,因为指针可以(错误地)很容易重置到另一个指针,并且可以通过另一个指针修改字符串,从而导致UB。
最大的区别可能是您不能对指针使用sizeof
操作符来获取开始指向的缓冲区的大小,而与const char[]
版本一样,您可以对数组变量使用sizeof
来以字节为单位获取数组的内存占用大小。所以这取决于你想用指针或缓冲区做什么,以及你想如何使用它。
例如:
void withPointer()
{
const char *sz = "hello";
std::cout << sizeof(sz) << std::endl;
}
void withArray()
{
const char sz[] = "hello";
std::cout << sizeof(sz) << std::endl;
}
会给你非常不同的答案。
一般来说,要回答这类问题,使用最明确的。
在这种情况下,const char[]
胜出,因为它包含了关于内部数据的更详细的信息——即缓冲区的大小。
提醒一下:
我选static const char sz[] = "hello";
。这样声明有一个很好的优点,即通过写入只读内存来更改常量字符串,从而使程序崩溃。如果没有static
,丢弃constness然后更改内容可能不会被注意到。
同样,static
允许数组仅仅位于常量数据部分,而不是在堆栈上创建,并在每次调用函数时从常量数据部分复制。
如果使用数组,则在运行时初始化数据。如果使用指针,运行时开销(可能)更少,因为只需要初始化指针。(如果数据小于指针的大小,则数据的运行时初始化小于指针的初始化。)所以,如果你有足够的数据并且你关心初始化的运行时成本,你应该使用指针。你几乎不应该关心这些细节。
几年前我从Ulrich Drepper的博客文章中得到了很多帮助:
如此接近,但没有雪茄和更多的数组乐趣
这个博客的要点是const char[]
应该是首选的,但只能作为全局变量或静态变量。
使用指针const char*
有如下缺点:
- 附加变量
- 指针可写
- 一个额外的间接
- 通过指针访问字符串需要2次内存加载
只是提一个小问题,表达式:
const char chararr[4] = {'t', 'e', 'x', 't'};
- 使用 fopen 打开 .pak 文件并使该文件应用于 const 无符号字符* (C++)
- 何时应在构造函数参数中使用 const C++?
- 何时使函数成为类成员函数C++?
- 不能使这种类型的"void(C::* volatile)(int) const "在参考手册C++示
- "move"和"const ref&"如何使双丁吉过载起作用?
- 何时必须使操作员<<过载?
- 在lambda中捕获各种向量使元素const
- 在Windows上,何时有必要将附加到目录路径上,以使_stat成功
- 将静态 const 成员重新声明为 constexpr 是否会自动使其符合内联条件
- STL容器及其元素的构成 - 何时使用const
- 继承,使基本成员变量const
- 如何使const char*函数起作用
- 使编译器假定 const primairy 类型作为类
- 自定义类的const实例化是否也会使类中的*everything*变为常量
- 为什么当 typedef const 指针与额外的 const 一起使用时,编译器不会给出错误?
- 如何使编译器在 const 未一致使用时至少发出警告
- 构造函数何时调用 const-expr
- 如何使const应用于c++类的共享指针成员
- 何时使用const char *,何时使用const char[]
- 使'const'使用类型特征的结果