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

template deduction: const reference and const pointer

本文关键字:const 引用 指针      更新时间:2023-10-16
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???

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

重要的是要认识到const仅在按值时被忽略参数。正如我们所看到的,对于引用- or的形参指向const的指针,expr的const性在类型期间保留扣除。

我想它的意思是

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

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

为什么引用的const被忽略,但指针的const没有?或者,为什么rx不是const int &呢?

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

关键是形参的类型,按值传递按引用传递/指针传递的行为改变。

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

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

正如书中所解释的,当const指针指向const (a const char* 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

param推导出的类型为const char*

只忽略顶级const/volatile限定符。其他的都是你这种类型的内在特质。换句话说,你在复制一个指针——这意味着函数在一个副本上操作,对它的任何修改(比如赋值另一个变量的地址)都不会修改原始指针。但是,如果将指针传递给const int,则让函数修改整型是非常违反直觉的。

template <typename T>
void f(T t)
{
    t = &another_variable; // ok
}
f(px);

void f(T t)
{
    *t = 42; // not ok!
}
f(px); // secretly modifying `x` through a pointer to const...

参考:这是const指针与const指针差异的答案