我正在运行一些示例程序来重新熟悉C ++,我遇到了以下问题。首先,这是示例代码:
void print_string(const char * the_string)
{
cout << the_string << endl;
}
int main () {
print_string("What's up?");
}
在上面的代码中,print_string的参数可能改为const char * const the_string
。哪个更合适呢?
我理解不同之处在于,一个是指向常量字符的指针,而另一个是指向常量字符的常量指针。但为什么这两个都有效呢?它何时相关?
答案 0 :(得分:224)
后者阻止您修改the_string
内的print_string
。它实际上在这里是合适的,但也许冗长会使开发人员失望。
char* the_string
:我可以将char
更改为the_string
点,我可以修改它所指向的char
。< / p>
const char* the_string
:我可以将char
更改为the_string
点,但我无法修改它所指向的char
。< / p>
char* const the_string
:我无法更改char
指向的the_string
,但我可以修改它指向的char
。< / p>
const char* const the_string
:我无法更改char
指向的the_string
,也无法修改指向的char
。< / p>
答案 1 :(得分:129)
指向可变字符的可变指针
char *p;
指向常量字符的可变指针
const char *p;
指向可变字符的常量指针
char * const p;
指向常量字符的常量指针
const char * const p;
答案 2 :(得分:26)
const char * const
表示指针以及指针指向的数据,都是 const!
const char *
表示仅指针指向的数据是const。然而,指针本身不是常量。
实施例
const char *p = "Nawaz";
p[2] = 'S'; //error, changing the const data!
p="Sarfaraz"; //okay, changing the non-const pointer.
const char * const p = "Nawaz";
p[2] = 'S'; //error, changing the const data!
p="Sarfaraz"; //error, changing the const pointer.
答案 3 :(得分:17)
(我知道这已经过时但我想分享。)
只是想详细说明Thomas Matthews&#39;回答。 C类型声明的左右规则几乎说:当读取C类型声明时,从标识符开始,然后在可以的时候向右移动,在可以的时候离开。
最好用几个例子来解释:
从标识符开始,我们无法向右移动
const char* const foo
^^^^^
foo是常量 ......
继续左转
const char* const foo
^
foo是指向的常量指针...
继续左转
const char* const foo
^^^^
foo是指向 char 的常量指针...
继续左转
const char* const foo
^^^^^
foo是一个常量指针,指向char 常量(完成!)
从标识符开始,我们无法向右移动
char* const foo
^^^^^
foo是常量 ......
继续左转
char* const foo
^
foo是指向的常量指针...
继续左转
char* const foo
^^^^
foo是指向 char 的常量指针(完成!)
从标识符开始,但现在我们可以走了!
const char* const* (*foo[8])()
^^^
foo是 8的数组 ...
点击括号,这样就不能再向左走,
const char* const* (*foo[8])()
^
foo是一个8 指针的数组 ...
在括号内完成,现在可以正确
const char* const* (*foo[8])()
^^
foo是一个指向函数的8指针数组,返回 ...
没有更多的东西,向左走
const char* const* (*foo[8])()
^
foo是一个8指向函数的数组,它返回指向的指针......
继续左转
const char* const* (*foo[8])()
^^^^^
foo是一个8指向函数的数组,它返回一个指向常量的指针 ......
继续左转
const char* const* (*foo[8])()
^
foo是一个8指向函数的数组,它返回一个指向指针的常量的指针...
继续左转
const char* const* (*foo[8])()
^^^^
foo是一个8指向函数的数组,它返回一个指向 char 的常量指针的指针......
继续左转
const char* const* (*foo[8])()
^^^^^
foo是一个8指向函数的数组,它返回一个指向char 常量的常量指针的指针(完成!)
答案 4 :(得分:12)
许多人建议从右到左阅读类型说明符。
const char * // Pointer to a `char` that is constant, it can't be changed.
const char * const // A const pointer to const data.
在两种形式中,指针指向常量或只读数据。
在第二种形式中,指针不能改变;指针总是指向同一个地方。
答案 5 :(得分:3)
不同之处在于,如果没有额外的const
,程序员可以在方法内部改变指针所指向的位置;例如:
void print_string(const char * the_string)
{
cout << the_string << endl;
//....
the_string = another_string();
//....
}
如果签名为void print_string(const char * const the_string)
许多程序员在额外的const
关键字中感觉过于冗长(在大多数情况下)并省略它,即使它在语义上是正确的。
答案 6 :(得分:2)
在后者中,您保证不会在第一个中修改指针和字符,只保证内容不会改变,但您可以移动指针
答案 7 :(得分:2)
没有理由说任何一个人都行不通。所有print_string()
都会打印该值。它不会尝试修改它。
最好不要将标记参数修改为const的函数。优点是无法更改(或者您不想更改)的变量可以毫无错误地传递给这些函数。
就确切的语法而言,您希望指出哪种类型的参数是“安全的”传递给函数。
答案 8 :(得分:2)
我认为它的变化很少相关,因为你的函数不会被调用像&amp; * the_string或** the_string这样的参数。指针本身是一个值类型参数,因此即使您修改它,也不会更改用于调用函数的副本。您显示的版本确保字符串不会更改,我认为在这种情况下就足够了。
答案 9 :(得分:2)
const char *
表示您无法使用指针来更改指向的内容。但是,您可以将指针更改为指向其他内容。
考虑:
const char * promptTextWithDefault(const char * text)
{
if ((text == NULL) || (*text == '\0'))
text = "C>";
return text;
}
该参数是一个指向const char的非const指针,因此它可以更改为另一个const char *
值(如常量字符串)。但是,如果我们错误地写了*text = '\0'
,那么我们就会收到编译错误。
可以说,如果您不打算更改参数指向的内容,您可以创建参数const char * const text
,但这样做并不常见。我们通常允许函数更改传递给参数的值(因为我们按值传递参数,任何更改都不会影响调用者)。
char const *
,因为它经常被误读 - 这意味着与const char *
相同,但有太多人将其视为含义char * const
。
答案 10 :(得分:1)
几乎所有其他答案都是正确的,但是他们错过了这方面的一个方面:当你在函数声明中对参数使用额外的const
时,编译器基本上会忽略它。暂时,让我们忽略您的示例作为指针的复杂性,并使用int
。
void foo(const int x);
声明与
相同的功能void foo(int x);
仅在函数的定义中,额外const
有意义:
void foo(const int x) {
// do something with x here, but you cannot change it
}
此定义与上述任一声明兼容。来电者并不关心x
是const
- 这是与呼叫网站无关的实施细节。
如果您有const
指向const
数据的指针,则适用相同的规则:
// these declarations are equivalent
void print_string(const char * const the_string);
void print_string(const char * the_string);
// In this definition, you cannot change the value of the pointer within the
// body of the function. It's essentially a const local variable.
void print_string(const char * const the_string) {
cout << the_string << endl;
the_string = nullptr; // COMPILER ERROR HERE
}
// In this definition, you can change the value of the pointer (but you
// still can't change the data it's pointed to). And even if you change
// the_string, that has no effect outside this function.
void print_string(const char * the_string) {
cout << the_string << endl;
the_string = nullptr; // OK, but not observable outside this func
}
很少有C ++程序员费心去做参数const
,即使它们可能也是如此,无论这些参数是否都是指针。
答案 11 :(得分:-1)
两者之间的区别在于char *可以指向任意指针。相反,Const char *指向可执行文件的DATA部分中定义的常量。因此,您无法修改const char * string的字符值。