auto *的类型扣除规则是什么?

时间:2016-04-15 16:17:23

标签: c++ templates auto decltype type-deduction

auto*的类型扣除规则是什么?

请考虑以下事项:

int x = 64;
int* px = &x;

auto* v1 = &x;    // auto => ???    ok v1 is int* ...
auto* v2 = px;    // auto => ???    is v2 int*  ?
auto* v3 = &px;   // auto => ???    is v3 int** ?

如果我们将类型演绎分为两个步骤,那么只是为了澄清我的问题:

  1. 在没有(auto)的情况下推断“*”的类型......然后
  2. 在添加(v1)后推断对象的类型(v2v3*
  3. 所以我的两个问题是:

    1. 如果没有(auto),*会推断出什么?
    2. v2会指向intint*)和v3指向指针(int**)吗?

4 个答案:

答案 0 :(得分:3)

output将推导出给定表达式的cv限定类型。 auto将推导出类型表达式的cv限定类型指向 - 如果expression是指针 - 否则将无法编译。

对于给定的示例,auto*的实际类型为v,与pointer to int相同,v2的实际类型为v3

如果您的第一个示例将写为pointer to pointer to int,则v1的类型将保持不变。

答案 1 :(得分:3)

您可以使用typeid来回答您的问题。

#include <iostream>
#include <typeinfo>
using namespace std;

int main() {
    // your code goes here
    int x = 64;
    int* px = &x;

    auto* v1 = &x;   
    auto* v2 = px;    
    auto* v3 = &px;   
    cout<<typeid(v1).name()<<endl;
    cout<<typeid(v2).name()<<endl;
    cout<<typeid(v3).name()<<endl;
    return 0;
}

输出:

Pi
Pi
PPi

Pi - &gt;指向整数变量的指针

PPi - &gt;指向整数变量指针的指针

答案 2 :(得分:1)

如果您知道模板类型扣除,您几乎可以了解auto 类型扣除。因为自动类型推导就像模板类型推导一样。

使用auto声明变量时,auto在模板中充当T,类型说明符充当参数类型:< / p>

const auto i = 20;

会转换为:

template<typename T>
void func(const T param) { ... }
//        ^^^^^^^

参考:

const auto& j = i;

转换为:

template<typename T>
void func(const T& param) 
//        ^^^^^^^^

使用指针,它是一样的:

auto* v1 = &x;

变为

template<typename T>
void func(T* param)

由于xint,因此auto* == int* auto* v2 = px;也是int*

现在,你拥有第三个:

auto* v3 = &px;

因为您正在获取指针的地址,所以变为int**

template<typename T>
void func(T** param)
//        ^^^

查看auto类型的一种方便方法是使用其他人提到的typeid()函数。
但我喜欢使用<boost/type_index.hpp>来正确显示类型:

#include <iostream>
#include <boost/type_index.hpp>
using namespace std;
using namespace boost::typeindex;

int main()
{
    int x = 64;
    int* px = &x;

    auto* v1 = &x;
    auto* v2 = px;
    auto* v3 = &px;
    cout << type_id_with_cvr<decltype(v1)>().pretty_name() << '\n';
    cout << type_id_with_cvr<decltype(v2)>().pretty_name() << '\n';
    cout << type_id_with_cvr<decltype(v3)>().pretty_name() << '\n';
}

哪个输出:

int*
int*
int**

自动类型扣除和模板类型扣除之间存在一个重要的差异,即std::initializer_list<>

请考虑以下示例:

auto i = 1;   // int
auto j(1);    // int
auto k = { 1 }// std::initializer_list<int> !
auto l { 1 }  // std::initializer_list<int> !

如您所见,使用带有auto的大括号初始化器可能会有麻烦 但是,您可以在大括号之前手动编写类型以确保类型正确但我不明白这一点:

auto i = int{ 1 }; // type is int

已经在Clang 3.8中实现了new auto rules,可以使用auto(即将推出的标准)直接列表初始化

答案 3 :(得分:0)

扣除过程与模板参数相同。如果我这样做:

int a = 0;
auto* b = &a;

b的类型为int*。写作:

auto b = &a;

会产生相同的类型int*。 在您的示例中,编译器将以某种方式添加缺失的星。但最简单的形式是写auto