模板推导:const 引用和const 指针

Yve*_*ves 6 c++ templates pointers reference template-argument-deduction

template <typename T>
void f(T t)
{}

int x = 1;
const int & rx = x;
const int * px = &x;
f(rx); // t is int
f(px); // t is const int *, instead of int *, WHY???
Run Code Online (Sandbox Code Playgroud)

我现在很困惑。根据Effective Modern c++

重要的是要认识到 const 仅被按值参数忽略。正如我们所见,对于const 引用或const 指针的参数,在类型推导过程中保留expr 的常量性。

我认为这意味着

template <typename T>
void f(T * t)
{}
f(px); // t is const int *

template <typename T>
void f(T & t)
{}
f(cx); // t is const int &

template <typename T>
void f(T t)
{}
f(value); // const or volatile of value will be ignored when the type of the parameter t is deduced
Run Code Online (Sandbox Code Playgroud)

所以我认为f(px)上面的时候,t应该是int *,但实际上是const int *

为什么constof 引用被忽略而constof 指针不是?或者,为什么不是rx const int &

son*_*yao 4

所以我觉得f(px)上面的时候,px应该是int *,但事实上确实是const int *

重点是参数的类型,按值传递按引用/指针传递的行为发生变化。

当按值传递时,参数本身的常量性将被忽略。对于指针参数,指针的常量性被忽略(const 指针 -> 指针),但被指针的常量性仍然保留(指向 const 的指针 -> 指向 const 的指针)。

它确实有意义,因为当传递指针时,指针本身被复制,但被指针是相同的,它们都指向同一个东西,所以被指针的常量性被保留;从调用者的角度来看,他们不希望对象被修改,他们可能会在以后使用它。在传递引用时(实际上引用在这里并不重要),您将复制一个全新的值,该值与原始值无关,然后忽略常量。

正如书中的以下解释,当指向 const (a const char* const) 的 const 指针传递时,

template<typename T>
void f(T param); // param is still passed by value

const char* const ptr = // ptr is const pointer to const object
  "Fun with pointers";

f(ptr); // pass arg of type const char * const
Run Code Online (Sandbox Code Playgroud)

推导出来的类型param将为const char*