Question

I am confused why the following code is not producing any error ,because the arguments passed to display are of same type i.e char.Does const really makes difference?

#include<iostream>

using namespace std;

void display(char *p)
{
    cout<<p;
}
void display(const char *p)
{
    cout<<p;
}

int main()
{
    display("Hello");
    display("World");
}

EDIT As per answers,the first display is never called,which is correct and so is the output.

But suppose I do it like :

int main()
{
    char *p="Hello";
    display(p);//now first display is called.
    display("World");
}

Compiler gives a warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] but then it calls first display.Does it mean that string is now no more taken as constant?

Was it helpful?

Solution

const char* and char * are actually not the same. The later allow for modifying the pointed char, while the first one will prevent that.

Also note that if those were class methods, void display() and void display() const would also be valid overloads. The later would imply that the method must not change the object's state.

Consider this code:

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);
}

This will print Display with const twice, and then twice Display. See there. Now, let's see why:

  • "llama" is a string literal, and then is resolved as a const char *.
  • str2 is a pointer to a string literal. Since its type is const char*, this also revolves to the const overload.
  • not_safe is also a pointer to a string literal. However, its type is char *: this is not correct. The memory it points to is read-only, and trying to modifies it will result in a crash. However, the type of the variable is still char *, so this resolve to the non-const overload.
  • str is a char * pointer, and the string it points to is not read-only. Modifying its content is valid, and since its type is char *, it will resolve to the non-const overload.

OTHER TIPS

The issue is that string literals such as "Hello" and "World" have type const char[6]. This can decay to const char*, but not to char*. So the overload taking const char*,

 void display(const char *p);

is the better match. As @JamesKanze points out, it would be possible for a function taking char* to accept a string literal, but attempting to modify the data pointed at would result in undefined behaviour. For this reason, it is unsafe to pass string literals to such functions. With suitable warning settings, GCC produces the following:

warning: deprecated conversion from string constant to ‘char*’

In any case, in the presence of two overloads like the ones you have shown, the one taking const char* wins.

The arguments passed to the two functions are actually not the same.

The first takes a char*: A pointer to a char.

The second takes a const char*: A pointer to a const char.

So you see, the difference here is actually in whether the pointer points to an object which can be changed or not. This is definitely a property on which you want to be able to overload a function.

Whether you can modify an object or not definitely is a useful piece of information depending on which you may want to invoke different behavior! Consider this:

void foo(int * p) { ++(*p); }
void foo(int const * p) { std::cout << *p << '\n'; }

The sizes of the strings "Hello" and "World" are known at compile time and cannot be modified. They are constant, compile-time character arrays.

In C and C++, an array e.g. char a[6] can be referred to using a pointer, i.e. a is actually a char *. Since the arrays for "Hello" and "World" must not be modified at runtime, their type is essentially const char *.

The compiler recognizes this and performs the overload resolution for display correctly, since only one of the functions (display(const char* p)) takes a const char* as an argument. This is why there is no ambiguity in the two functions, and you don't get the error that you expected to get.

"because the arguments passed to display are of same type i.e char."

No here the argument are "const char*". the data type is the but the const qualifier indicate that the literal string you hard coded, is not something that can be change.

"Does const really makes difference?"

Yes the const qualifier make a difference. in Display(char*) you can update the content of the null-terminate string you passed but not in Display(const char*). That fact allow more optimization by the compiler.

But read that http://www.possibility.com/Cpp/const.html it's a good source to start using const efficiently.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top