我很困惑为什么下面的代码没有产生任何错误,因为传递给display的参数属于同一类型,即char
。const
真的有区别吗?
#include<iostream>
using namespace std;
void display(char *p)
{
cout<<p;
}
void display(const char *p)
{
cout<<p;
}
int main()
{
display("Hello");
display("World");
}
修改 根据答案,永远不会调用第一个显示,这是正确的,输出也是如此。
但是假设我这样做:
int main()
{
char *p="Hello";
display(p);//now first display is called.
display("World");
}
编译器给出一个warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
但是它先调用display.Does意味着字符串现在不再被视为常量?
答案 0 :(得分:11)
const char*
和char *
实际上并不相同。后者允许修改指向char
,而第一个则会阻止它。
另请注意,如果这些是类方法,void display()
和void display() const
也是有效的重载。后者意味着方法不能改变对象的状态。
考虑以下代码:
void display(char *s)
{
std::cout << "Display" << std::endl;
}
void display(const char *s)
{
std::cout << "Display with const" << std::endl;
}
int main()
{
char *str = strdup("boap");
const char *str2 = "toto";
/* It is a string literral "bound" as a char *.
Compiler will issue warning, but it still compiles.
Avoid to do that, it's just an exemple */
char *not_safe = "not_safe";
display("llama");
display(str2);
display(str);
display(not_safe);
}
这将打印Display with const
两次,然后两次Display
。见there。
现在,让我们看看为什么:
"llama"
是一个字符串文字,然后被解析为const char *
。str2
是指向字符串文字的指针。由于其类型为const char*
,因此也会转为const
重载。not_safe
也是指向字符串文字的指针。但是,其类型为char *
:这不正确。它指向的内存是只读的,尝试修改它会导致崩溃。但是,变量的类型仍为char *
,因此解决了非const
重载问题。str
是一个char *
指针,它指向的字符串不是只读的。修改其内容是有效的,因为它的类型为char *
,它将解析为非const重载。答案 1 :(得分:3)
问题是"Hello"
和"World"
等字符串文字的类型为const char[6]
。这可以衰减到const char*
,但不会衰减到char*
。所以过载需要const char*
,
void display(const char *p);
是更好的匹配。正如@JamesKanze指出的那样,有一个函数可以使char*
接受一个字符串文字,但是试图修改指向的数据会导致未定义的行为。因此,将字符串文字传递给此类函数是不安全的。通过适当的警告设置,GCC产生以下内容:
警告:已弃用从字符串常量转换为'char *'
在任何情况下,如果出现两次重载,例如你所显示的重载,那么const char*
的重载就会胜出。
答案 2 :(得分:0)
传递给这两个函数的参数实际上并不相同。
第一个采用char*
:指向char
的指针。
第二个采用const char*
:指向const char
的指针。
所以你看,这里的区别实际上在于指针是否指向一个可以改变的对象。这绝对是您希望能够重载函数的属性。
答案 3 :(得分:0)
您是否可以修改对象绝对是一个有用的信息,具体取决于您可能想要调用不同的行为!考虑一下:
void foo(int * p) { ++(*p); }
void foo(int const * p) { std::cout << *p << '\n'; }
答案 4 :(得分:0)
字符串“Hello”和“World”的大小在编译时是已知的,不能修改。它们是常量的编译时字符数组。
在C和C ++中,一个数组,例如可以使用指针引用char a[6]
,即a
实际上是char *
。由于“Hello”和“World”的数组不能在运行时修改,因此它们的类型基本上是const char *
。
编译器识别出这一点并正确执行display
的重载解析,因为只有一个函数(display(const char* p)
)将const char*
作为参数。这就是为什么这两个函数没有歧义,你没有得到你期望得到的错误。
答案 5 :(得分:0)
“因为传递给display的参数是相同的类型,即char。”
这里没有参数是“const char *”。数据类型是但是const限定符表示你硬编码的文字字符串不是可以改变的东西。
“const真的有区别吗?”
是的const限定符有所作为。 在Display(char *)中,您可以更新传递的null-terminate字符串的内容,但不能更新Display(const char *)。这一事实允许编译器进行更多优化。
但请阅读http://www.possibility.com/Cpp/const.html这是开始有效使用const的好资源。