【问题标题】:Const in auto type deduction自动类型扣除中的 const
【发布时间】:2026-01-28 00:50:02
【问题描述】:

我正在阅读 Scott Meyers 的《Effective modern C++》。第 1 项包含以下示例:

template<typename T>
void f(T& param);       // param is a reference
int x = 27;             // x is an int
const int cx = x;       // cx is a const int
f(cx);                  // T is const int,
                        // param's type is const int&

在第 3 项中出现以下示例:

Widget w;
const Widget& cw = w;
auto myWidget1 = cw;             // auto type deduction:
                                 // myWidget1's type is Widget

根据第 1 项,我预计 myWidget1 的类型是 const Widget。我错过了什么吗?

【问题讨论】:

  • auto&amp; 等同于 T&amp;
  • @Piotr Skotnick:谢谢!
  • 在我所谓的“正确表达式”上,在= 的右侧(普通赋值,复制初始化)和按值参数传递,const 无关紧要;在 ref 绑定的 = 右侧,const 确实很重要。
  • 尝试使用T param(即没有参考),然后你会看到与auto myWidget1的相似之处......或者使用auto &amp; myWidget1T &amp; param相同。

标签: c++ c++11 reference auto effective-c++


【解决方案1】:

auto myWidget1 = cw; 遵循 Meyers 书中模板参数类型推导的第三条规则,即按值传递。 当您按值传递时,cv 限定符和引用将被忽略,因为您正在获取对象的新副本,因此您并不真正关心您从中复制的旧对象是 const 还是引用。

【讨论】:

    【解决方案2】:

    大多数情况下auto遵循模板参数推导规则:

    § 7.1.6.4 [dcl.spec.auto]/p6:

    一旦根据 8.3 确定了 declarator-id 的类型,声明变量的类型 使用 declarator-id 由使用模板参数规则的初始值设定项类型确定 扣除。令T 为已为变量标识符d 确定的类型。从T获取P 用新发明的类型模板参数U 替换出现的auto,或者,如果初始化程序 是一个 braced-init-list (8.5.4),带有std::initializer_list&lt;U&gt;。为变量 d 推导的类型然后是使用从函数调用 (14.8.2.1) 的模板参数推导规则确定的推导 A

    § 14.8.2.1 [temp.deduct.call]/p2:

    如果P 不是引用类型:

    • [...]

    • 如果 A 是 cv 限定类型,则 A 类型的* cv 限定符将被忽略以进行类型推导

    如果您希望myWidget1 的类型为const Widget&amp;,则应将其声明为引用类型,例如:

    auto& myWidget1 = cw;
    //  ^
    

    DEMO

    【讨论】:

    • 'should' 在这里是错误的关键字,你'可以' 将其声明为auto&amp;。也可以指定constkeyword,效果一样。
    最近更新 更多