Why are const qualifiers in function arguments use

2019-04-05 13:51发布

Possible Duplicate:
Functions with const arguments and Overloading

I am pretty confused by the overloading and const declaration rules. Here are two things that puzzle me maybe you can help me find the deeper misunderstanding in my head that result in them being puzzling to me. ;)

First issue:

My compiler allows this:

void f(int & x) {
  std::cout << "plain f" << std::endl;
}
void f(const int & x) {
  std::cout << "const f" << std::endl;
}

But the following causes a compile error (function already has a body):

void f(int x) {
  std::cout << "plain f" << std::endl;
}
void f(const int x) {
  std::cout << "const f" << std::endl;
}

Which I suppose makes sense because I thought the const was only there to tell the compiler that the object being passed is not changed and in the second case it is copied anyway. But if that is correct then why can I overload functions using const?

In other words, why if I use the compiling version and call the functions like this:

  int x1 = 5;
  const int x2 = 5;
  f(x1);
  f(x2);

do I get "plain f" and "const f" instead of "const f" twice? Apparently now I am also using the const to tell the compiler which function to call not only that the reference doesn't change. This gets more confusing because if I remove the "plain" version it works just fine and calls the "const" version twice.

Now what is my actual question? I would like to know what the ideas behind this behavior are because otherwise memorizing it is very hard.

2条回答
再贱就再见
2楼-- · 2019-04-05 14:02

I thought the const was only there to tell the compiler that the object being passed is not changed and in the second case it is copied anyway

You are correct. Because in the second case it's copied anyway, and so the const makes no difference to the caller, the standard defines that void f(const int x) and void f(int x) have the same signature. Hence they collide, you're trying to define the same function twice.

Because in the first case it isn't copied anyway, void f(const int &x) and void f(int &x) have different signatures. Hence they overload.

In your first case, it's forbidden to call the int& version of f with x2 as argument, because that would create a non-const reference to a const object without any explicit cast in sight. Doing that defeats the purpose of the const system (which is that if you want to break const-safety, you have to do so explicitly with a cast). So it makes sense to have const- and non-const overloads of functions with reference parameters.

In your second case, there's no relation between the const-ness of the source of a copy, and the const-ness of the destination. You can initialize a const variable from a non-const one, or a non-const one from a const one. This causes no problems and doesn't break const-safety. That's why the standard helpfully makes this clear by defining that your two "different" versions of f are actually the same function.

查看更多
劫难
3楼-- · 2019-04-05 14:14

n3337 13.1

[ Note: As specified in 8.3.5, function declarations that have equivalent parameter declarations declare the same function and therefore cannot be overloaded: ffer only in the presence or absence

— Parameter declarations that di3 of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called. [ Example:

typedef const int cInt;
int f(int);
int f(const int); // redeclaration of f(int)
int f(int) { /* ... */ } // definition of f(int)
int f(cInt) { /* ... */ } // error: redefinition of f(int)

— end example ] Only the const and volatile type-specifiers at the outermost level of the parameter type specifica- tion are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.124 In particular, for any type T, “pointer to T,” “pointer to const T,” and “pointer to volatile T” are considered distinct parameter types, as are “reference to T,” “reference to const T,” and “reference to volatile T.”

查看更多
登录 后发表回答