模板推导:常量引用和常量指针

6
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只对按值传递的参数无效。正如我们所看到的那样,对于引用或指向常量的指针参数,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&


1
回复:“为什么rx不是const int &?”:如果您编写f<const int &>(rx),它可以是const int &(而f<int &>(rx)将无效)。但是,同样地,您也可以编写f<const int &>(x)。因此,rx的引用性与模板参数推断无关;它被视为只是一个const int - ruakh
2个回答

4
所以我认为当f(px)出现时,px应该是int *,但实际上它是const int *
关键在于参数的类型,对于传值和传引用/指针,行为会发生改变。
当传值时,参数本身的const属性被忽略。对于指针参数,指针的const属性被忽略(const指针->指针),但pointee的const属性仍然被保留(指向const的指针->指向const的指针)。
这是有道理的,因为传递指针时,指针本身被复制,但pointee是相同的,它们都指向同一个东西,因此pointee的const属性得以保留。从调用者的角度来看,他们不希望对象被修改,他们可能稍后再使用它。而当传递引用(实际上这里引用没有影响)时,你将获得一个全新的值副本,与原始值没有任何关系,然后const性被忽略。
根据书中以下的解释,当传递const指向const的指针(如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
< p > 对于param推断出的类型将是const char*。< /p >

我感到困惑,因为我认为引用的常量性也应该被保留。在我的例子中,我认为rx应该是const int &,而不是int。我一直认为引用和指针有点相似。但是,我错了。 - Yves
1
@Thomas 不同之处在于当你传递一个指针时,指针本身被复制,但指向的对象是相同的,它们都指向同一件事物,因此指向对象的常量性得以保留。而当你传递一个引用时,你会得到一个全新的值副本,与原始值无关,然后常量性被忽略了。 - songyuanyao

2

只有顶层const/volatile限定符会被忽略,其他都是类型的固有属性。换句话说,你正在复制一个指针 - 这意味着函数操作的是副本,对其进行的任何修改(比如分配另一个变量的地址)都不会修改原始指针。但如果你传递一个指向常量整数的指针,则让函数修改整数非常反直觉。

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...

参考:这个答案,讲解指向常量的指针和常量指针的区别。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接