首页 > 解决方案 > auto 如何决定变量的类型?

问题描述

#include <iostream>
int main() 
{
    auto n {42};
    cout << "The n has value of " << n <<
    " and a size of " << sizeof(n) << endl; // Works as expected
}
#include <iostream>
int main() 
{
    auto n = {42};
    cout << "The n has value of " << n <<
    " and a size of " << sizeof(n) << endl; // Does not work!
}

这是为什么?在“A Tour of C++”中明确指出:

1.4.2 初始化 在一个对象可以使用之前,它必须被赋予一个值。C++ 提供了多种表示初始化的符号,例如上面使用的 =,以及基于花括号分隔的初始化列表的通用形式:

    double d1 = 2.3; // initialize d1 to 2.3  
    double d2 {2.3}; // initialize d2 to 2.3  
    double d3 = {2.3}; // initialize d3 to 2.3 (the = is optional with { ... })
    complex<double> z2 {d1,d2};   
    complex<double> z3 = {d1,d2}; // the = is optional with { ... }  

=是可选的{}
那么,为什么会这样呢?

标签: c++c++11

解决方案


这受[dcl.type.auto.deduct]的规则约束,特别是[dcl.type.auto.deduct]/1[dcl.type.auto.deduct]/4 [强调我的]:

[dcl.type.auto.deduct]/1

占位符类型推导是将包含占位符类型的类型替换为推导类型的过程。

[dcl.type.auto.deduct]/4

如果占位符是类型说明符,则使用模板参数推导的规则确定auto推导的类型T' 替换。通过用新发明的类型模板参数替换出现的 或,如果初始化是复制列表初始化,用 . 使用模板实参推导规则从函数调用中推导出一个值,其中是 函数模板形参类型,对应的实参是。如果扣除失败,则声明格式错误。否则,通过将推导代入得到。[ 例子:TPTautoU std​::​initializer_­list<U>UPeT'UP

auto x1 = { 1, 2 };    // decltype(x1) is std​::​initializer_­list<int>
auto x2 = { 1, 2.0 };  // error: cannot deduce element type
auto x3{ 1, 2 };       // error: not a single element
auto x4 = { 3 };       // decltype(x4) is std​::​initializer_­list<int>
auto x5{ 3 };          // decltype(x5) is int

 —结束示例]

您的第二个示例是使用复制列表初始化,含义auto被替换为,使用模板参数推导规则,std::initializer_list<U>,其中U进一步推导为int

auto n {42};    // deduced type is 'int'
auto m = {42};  // deduced type is 'std::initializer_list<int>'

这些规则特别适用于占位符类型扣除,因此不适用于非占位符类型的情况;op 的后一个示例已经指定了类型并且适用非类型扣除。

// no placeholder type: type is 'double', and 'd1'
// through 'd3' simply uses different ways to initialize
// an object of (non-class fundamental) type 'double'.
double d1 = 2.3;   // copy initialization
double d2 {2.3};   // direct-list initialization; no narrowing allowed
double d3 = {2.3}; // copy-list-initialization (from C++11); no narrowing allowed

推荐阅读