6

我很困惑为什么下面的代码没有产生任何错误,因为传递给 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]但随后它调用了第一个显示。这是否意味着该字符串现在不再被视为常量?

4

6 回答 6

11

const char*char *实际上是不一样的。后者允许修改 point 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。见那里。现在,让我们看看为什么:

  • "llama"是字符串文字,然后被解析为const char *.
  • str2是指向字符串文字的指针。由于它的类型是const char*,这也与const重载有关。
  • not_safe也是一个指向字符串文字的指针。但是,它的类型是char *这是不正确的。它指向的内存是只读的,尝试修改它会导致崩溃。但是,变量的类型仍然是char *,所以这解决了非const重载。
  • str是一个char *指针,它指向的字符串不是只读的。修改它的内容是有效的,因为它的类型是char *,它会解析为非常量重载。
于 2013-07-26T07:29:02.323 回答
3

问题是字符串文字,例如"Hello"and"World"具有 type const char[6]。这可以衰减到const char*,但不会衰减到char*。所以过载const char*

 void display(const char *p);

是更好的匹配。正如@JamesKanze 指出的那样,函数char*可以接受字符串文字,但尝试修改指向的数据会导致未定义的行为。因此,将字符串文字传递给此类函数是不安全的。使用适当的警告设置,GCC 会产生以下结果:

警告:不推荐将字符串常量转换为 'char*'</p>

在任何情况下,如果存在像您所展示的那样的两个重载,则const char*取胜的那个。

于 2013-07-26T07:36:30.053 回答
0

字符串“Hello”和“World”的大小在编译时是已知的,不能修改。它们是常量,编译时字符数组。

在 C 和 C++ 中,数组 egchar a[6]可以使用指针来引用,即a实际上是一个char *. 由于“Hello”和“World”的数组不能在运行时修改,它们的类型本质上是const char *.

编译器认识到这一点并正确执行重载决议display,因为只有一个函数 ( display(const char* p)) 将 aconst char*作为参数。这就是为什么这两个函数没有歧义,并且您不会得到预期的错误。

于 2013-07-26T07:33:24.610 回答
0

您是否可以修改对象绝对是一条有用的信息,具体取决于您可能想要调用不同的行为!考虑一下:

void foo(int * p) { ++(*p); }
void foo(int const * p) { std::cout << *p << '\n'; }
于 2013-07-26T07:29:52.553 回答
0

“因为传递给显示的参数是相同的类型,即字符。”

不,这里的论点是“const char *”。数据类型是,但 const 限定符表明您硬编码的文字字符串不是可以更改的。

“ const 真的有区别吗?”

是的, const 限定符有所作为。在 Display(char*) 中,您可以更新您传递的空终止字符串的内容,但不能在 Display(const char*) 中更新。这一事实允许编译器进行更多优化。

但是请阅读http://www.possibility.com/Cpp/const.html这是开始有效使用 const 的好来源。

于 2013-07-26T07:35:20.120 回答
0

传递给这两个函数的参数实际上并不相同。

第一个需要 a char*:指向 a 的指针char

第二个接受 a const char*:指向 a 的指针const char

所以你看,这里的区别实际上在于指针是否指向可以更改的对象。这绝对是您希望能够重载函数的属性。

于 2013-07-26T07:25:37.443 回答