请教一个 c++问题, auto 定义多个对象时的指针类型推演 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zby0826
V2EX    C

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

  •  
  •   zby0826 2016-06-10 11:12:38 +08:00 via Android 2623 次点击
    这是一个创建于 3459 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 = &c, 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     Solana     2760 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 08:30 PVG 16:30 LAX 00:30 JFK 03:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86