1

我正在阅读 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。我错过了什么吗?

4

2 回答 2

3

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

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

一旦根据 8.3 确定了declarator-id的类型,使用declarator-id声明的变量的类型就使用模板参数推导规则从其初始值设定项的类型中确定。让T是已为变量标识符确定的类型d。通过将出现的 替换为P新发明的类型模板参数,或者如果初始值设定项是花括号初始化列表(8.5.4),则使用. 为变量推导的类型然后使用从函数调用 (14.8.2.1) 的模板参数推导规则确定推导。TautoUstd::initializer_list<U>dA

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

如果P不是引用类型:

  • [...]

  • 如果是 cv 限定类型,则's 类型A的顶级 cv 限定符对于类型推导将被忽略A

如果您想myWidget1成为 type const Widget&,则应将其声明为引用类型,例如:

auto& myWidget1 = cw;
//  ^

演示

于 2015-08-07T08:44:26.643 回答
1

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

于 2015-08-07T22:03:33.303 回答