Recursive variable declaration
我刚刚在《愚蠢的执行者》和《手册执行者》中看到了这种黑色魔法。
1
| TimePoint now_ = now_.min(); |
在我对整个库源代码进行grep之后,除了这里,我在任何地方都没有看到变量now_的定义。这里发生了什么?这是某种有效的递归变量声明吗?
- 我认为,如果你提供了TimePoint文档的链接(如果在Web上可用),或者增加了TimePoint::min()的声明(复制粘贴.h文件中的相关行,如果它编译的话,你必须拥有这些行),这个问题就可以得到改进。
- 另请参见:stackoverflow.com/questions/3255555/…
- 还有另一种混淆代码的方法……
- 看起来有点像Java中的EDOCX1 2Ω…
- @MDXF:是……但是避免重复typename,如果它需要模板参数或是限定的话,这可能会很长。
- 搜索时间点会让你做得更好。
- fwiw,我遇到了这个stackoverflow问题,并将其修补为不必要的不透明:github.com/facebook/folly/commit/…
该代码很可能等于:
1
| TimePoint now_ = TimePoint::min(); |
也就是说,min()是一个静态方法,使用实例调用它和这样调用它是一样的,该实例仅用于确定类型。不涉及黑魔法,这只是两种语法,用来做同样的事情。
关于所讨论的代码编译的原因:now_已经由行的左侧声明,所以当它用于在右侧初始化时,编译器已经知道它的类型,并且能够调用静态方法。尝试调用非静态方法时应给出错误(请参见下面@benvoigt的注释)。
正如您必须编写这个问题的事实所证明的那样,问题中的语法不是最清楚的。如果类型名太长可能很诱人,并且在带有初始值设定项的成员变量声明中可能是合理的(问题代码就是这样)。在代码内部函数中,auto是减少重复的更好方法。
- 从编译器的角度来看,这两种编写方法是等效的。在代码评审中,只有一个是可以接受的。我把它作为练习留给读者去猜哪一个。
- @科迪格雷,是的,每个人都知道你对四点邪恶的仇恨。合理点,科迪:有时最好选择::!
- dilbert.com/strip/1994-06-08
- 初始值设定项的非静态case值计算分析是在复制构造函数调用之前排序的(此语法是复制初始化),因此构造函数尚未开始执行,因此对象的生存期尚未开始。本标准第3.8节规定,"在对象的寿命开始之前,但在分配了对象将占用的存储之后,可以使用引用原始对象的ny glvalue,但只能以有限的方式使用。程序有UNDE?ned behavior if:glvalue用于调用对象的非静态成员函数。"
- OP引用的代码实际上是一个非静态数据成员,其中auto不可用。
- @T.C.嗯,你能解释更多吗?根据Mikel F的答案,在我看来,方法static constexpr time_point min()。
- @海德·埃多克斯1〔2〕是静态的。问题是,now_实际上是某个类的非静态数据成员,而now_.min()实际上是它的默认成员初始值设定项。
- "T.C. Ah!我想这可能需要在不点击链接的情况下稍微编辑一下问题,给出正确的上下文。谢谢。
深入研究代码表明,时间点是chrono::steady_clock::time_point的别名,其中min()实际上是一个静态方法,返回允许的最短持续时间:
http://en.cppreference.com/w/cpp/chrono/time_point/min/分钟