V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zby0826
V2EX  ›  C

请教一个 c++问题, auto 定义多个对象时的指针类型推演

  •  
  •   zby0826 · 2016-06-10 11:12:38 +08:00 via Android · 2170 次点击
    这是一个创建于 3080 天前的主题,其中的信息可能已经有所发展或是发生改变。
    C++ primer 中文第五版 62 页:
    int i = 0;
    const int ci = i;
    auto e = &ci;
    e 是一个指向整型常量的指针(对常量对象取地址是一种底层 const)
    以上可以理解。

    下面又说:
    要在一条语句中定义多个变量,切记,符号&和*只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一种类型:

    auto &m = ci, *p = &ci; // m 是对整型常量的引用, p 是指向整型常量的指针



    既然说初始值必须是同一种类型,可是 ci 和&ci 明明不是同一种类型啊!
    为什么合法?为什么 p 是指向整型常量的指针,而不是指向整型常量指针的指针?为什么 auto 被推演为 const int 所以表达式合法?为什么 auto 不是被推演为 const int* 然后表达式就不合法了呢?


    是不是定义多个变量有什么机制??
    如果单独定义 auto *p2 = &ci; 那么 p2 是不是就变为指向整型常量指针的指针了呢?是不是这里的 auto 就被推演为 const int*了呢?

    为什么会有这种差异?

    手机码字,格式什么的可能不太好,抱歉。
    14 条回复    2016-06-11 10:35:33 +08:00
    Sorrow
        1
    Sorrow  
       2016-06-10 11:49:00 +08:00
    auto &m = ci, *p = &ci;
    如果你不理解这行代码,请把 auto 换成 const int :
    代码就变为:
    const int &m = ci, *p = &ci;
    zby0826
        2
    zby0826  
    OP
       2016-06-10 11:51:08 +08:00 via Android
    @Sorrow &ci 是指针,为什么不推演为 const int*
    kindjeff
        3
    kindjeff  
       2016-06-10 11:59:59 +08:00
    语法上的不统一啦, auto *p2 = &ci 和 auto p2 = &ci 推导出来是一样的
    kindjeff
        4
    kindjeff  
       2016-06-10 12:12:18 +08:00   ❤️ 1
    我想了一下应该把 auto 看做占位符, auto *p2 = &ci 的时候推导出来'auto'=='const int', auto p2 = &ci 的时候推导出来'auto'=='const int *'。
    auto &m = ci, *p = &ci 的时候推导出来'auto'=='const int'。所以你写 auto *p = ci 就会报错,因为推导不出来 auto 这个位置应该放什么。
    loveuqian
        5
    loveuqian  
       2016-06-10 12:21:17 +08:00
    突然想起来。。轮子哥不混 v2 的啊?
    @vczh
    Sorrow
        6
    Sorrow  
       2016-06-10 12:23:49 +08:00
    @zby0826 auto 是一个 placeholder ,它的用法和其他 declarator 一致,如果按照你的理解就破坏了这种语法规则。
    onemoo
        7
    onemoo  
       2016-06-10 14:45:34 +08:00   ❤️ 1
    我觉得这个应该算是翻译时用词的问题。
    描述这段相应的原文中是这样的:
    “ Because a declaration can involve only a single base type, the initializers for all the variables in the declaration must have types that are consistent with each other ”
    我粗译一下:
    因为一句声明只能有一个 base type (这里的 base type 指的是 auto 所代表的类型),所以多个(被声明的)变量的 initializer 的类型必须能够相互配合一致。

    “ The type that the compiler infers for auto is not always exactly the same as the initializer ’ s type ”
    ——编译器推断出来的 auto 类型并非一定与 initializer 的类型一致
    “ when we use a reference as an initializer, the initializer is the corresponding object ”
    ——当我们用引用作为 initializer ,我们其实用的是“被引用的对象”,(推断出的也是被引用对象的类型)
    这几句的意思就是初值的类型不一定和 auto 类型一致,只要它们能匹配“通常的声明规则”即可。 使用 auto 时,通常的声明规则仍是有效的。

    所以,我感觉不应翻译为“因此初始值必须是同一种类型”,因为原文中始终用的是 consistent 而非 same ,原意为:后面各个变量的初始值的类型,必须能够[互相]与 auto 匹配。

    你最后所说:如果单独定义 auto *p2 = &ci; 那么 p2 是不是就变为指向整型常量指针的指针了呢?是不是这里的 auto 就被推演为 const int*了呢?
    这个 auto 就会被推断为 const int 类型, auto *p2 即是 const int *p2 , p2 不正是 const int 指针吗。
    zby0826
        8
    zby0826  
    OP
       2016-06-10 15:37:31 +08:00 via Android
    @onemoo 首先谢谢…
    你说的是中文版前面一页 p61 ,其实中文版也说了“编译器推断出来的 auto 类型有时候和初始值的类型并不完全一致,编译器会适当的改变结果类型使其更符合初始化规则”。但这里没有详细解释什么叫更符合初始化规则。
    你最后的意思是 p2 是指针,不是指向指针的指针?这么说的话, auto *p2 = &ci; 和 auto p2 = &ci; 没有区别?所定义的 p2 就是完全一样的?在上自习,没带电脑,晚上回去跑一下看看…
    zby0826
        9
    zby0826  
    OP
       2016-06-10 15:45:18 +08:00 via Android
    @kindjeff 为什么 auto *p2 = &ci 和 auto p2 = &ci 推导出来是一样的?

    “ auto *p2 = &ci 的时候推导出来'auto'=='const int', auto p2 = &ci 的时候推导出来'auto'=='const int *'。”为什么会这样?依据是什么呢?前者为什么不能解释为指向指针的指针呢?
    kindjeff
        10
    kindjeff  
       2016-06-10 15:52:24 +08:00 via iPhone   ❤️ 1
    @zby0826 因为&ci 就是一个 const int*呀
    zby0826
        11
    zby0826  
    OP
       2016-06-10 16:20:43 +08:00 via Android
    @kindjeff 我明白了,绕了个大圈子,我以为可以解释为 const int **p2 = &ci ,然而这句表达式本身就是完全错误的。所以疑惑都解开了,可能正如你所说 auto 就是类似占位符,对不同的声明符和类型修饰符做出不同的说明。谢谢了~
    onemoo
        12
    onemoo  
       2016-06-10 16:48:16 +08:00
    所以, auto 相当于一道填空题:“____ *p2 = &ci ,请填入一个类型,使该表达式合法成立”。
    你会填入 const int ,编译器也会推导出相同的结果,这个结果就是 auto 的类型。 你写出这个答案的依据就是你所学过的的“普通的声明规则”。
    我给出前一页的那句话是因为:它所描述的就是这两页中的所有内容的原则。 也就是说等号左侧和右侧的这些类型必须是相互 consistent 的,判断是否 consistent 依据的就是 C++自身的“声明规则”。

    关于 9L 中你的问题,“ auto *p2 = &ci 的时候推导出来'auto'=='const int', auto p2 = &ci 的时候推导出来'auto'=='const int *” 是的,会推导出这样的结果,原因现在你已经明白了吧。
    但是如果这句是这样写的: auto *p2 = &ci, p3 = &ci; 就错了。因为根据 p2 ,编译器推导出 auto 应为 const int ,但根据 p3 ,又推导出了 auto 为 const int *,两者 inconsistent ,编译器就会报错了。
    FrankHB
        13
    FrankHB  
       2016-06-11 05:17:35 +08:00
    什么 base type ……现在的“入门”书已经没节操在这里生造概念了吗……难怪某糖看不起“底火”……
    有点正确的基础的话真的就是一句话的事情……
    WG21/N4594
    7.1.6.4 auto specifier [dcl.spec.auto]
    1 The auto and decltype(auto) type-specifiers are used to designate a placeholder type that will be replaced
    later by deduction from an initializer. ...
    (当然怎么 deduce 就要倒腾 Clause 14 了,没问题就可喜可贺。)
    bravecarrot
        14
    bravecarrot  
       2016-06-11 10:35:33 +08:00 via iPhone
    auto 不可以替换的哦
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5192 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 03:48 · PVG 11:48 · LAX 19:48 · JFK 22:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.