【问题标题】:template deduction: const reference and const pointer模板推导:const引用和const指针
【发布时间】:2016-10-21 02:26:52
【问题描述】:
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 的常量 扣除。

我认为这意味着

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 &amp;?

【问题讨论】:

  • 回复:“为什么不是rxconst int &amp;?”:可以,如果你写f&lt;const int &amp;&gt;(rx)(而f&lt;int &amp;&gt;(rx) 无效)。但是,就此而言,您也可以写f&lt;const int &amp;&gt;(x)。所以rx的引用与模板参数推导无关;它被视为与const int 一样。

标签: c++ templates pointers reference template-argument-deduction


【解决方案1】:

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

重点是参数的类型,passed-by-value和passed-by-reference/pointer的行为变化。

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

这确实是有道理的,因为当传递一个指针时,指针本身被复制了,但是指针对象是相同的,它们都指向同一个东西,所以指针对象的常量性被保留了;从调用者的角度来看,他们不希望对象被修改,他们可能会在以后使用它。在传递引用时(这里其实引用无关紧要),你会得到一个全新的值被复制,它与原来的值无关,然后忽略 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

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

【讨论】:

  • 我很困惑,因为我认为引用的常量也应该保留。在我的示例中,我认为 rx 应该是 const int &amp;,而不是 int。我一直认为引用与指针是一回事。好吧,我错了。
  • @Thomas 不同的是,当你传递一个指针时,指针本身会被复制,但是指针是相同的,它们都指向同一个东西,所以指针的常量被保留了。当你传递一个引用时,你会得到一个复制的全新值,它与原始值无关,然后忽略 constness。
【解决方案2】:

只有顶级 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...

参考:this answer 指向 const 指针与 const 指针的区别

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    相关资源
    最近更新 更多