为什么我更喜欢明确给出类型的“显式类型化初始化器”习惯用法

时间:2014-09-01 13:45:22

标签: c++ c++11 effective-c++

我最近从Scott Meyers那里购买了新的Effective现代C ++,现在正在阅读它。但是我遇到了一件事,那让我很烦恼。

在第5项中Scott说,使用auto是一件好事。它可以节省打字,在大多数情况下会为您提供正确的类型,并且可能不会出现类型不匹配的情况。我完全理解这一点,并认为auto也是一件好事。

但是在第6项中斯科特告诉我,每枚硬币都有两面。同样可能存在auto推断完全错误类型的情况,例如代理对象。

您可能已经知道这个例子:

class Widget;
std::vector<bool> features(Widget w);

Widget w;

bool priority = features(w)[5]; // this is fine

auto priority = features(w)[5]; // this result in priority being a proxy
                                // to a temporary object, which will result
                                // in undefined behavior on usage after that
                                // line

到目前为止,非常好。

但斯科特对此的解决方案是所谓的&#34;明确类型化的初始化用户&#34;。我的想法是,在初始化程序上使用static_cast,如下所示:

auto priority = static_cast<bool>(features(w)[5]);

但这不仅会导致更多的输入,而且还会明确说明应该推断出的类型。你基本上失去了auto优于给定显式类型的优点。

任何人都可以告诉我,为什么使用这个成语是有利的?


首先要澄清问题,我的问题旨在为什么要写:

auto priority = static_cast<bool>(features(w)[5]);

而不是:

bool priority = features(w)[5];

@Sergey提出了关于GotW关于这个主题的好文章的链接,这部分回答了我的问题。

  

指南:考虑声明局部变量auto x = type {expr};当你想要显式提交一个类型。它是自我记录的,表明代码明确地请求转换,它保证变量将被初始化,并且它不允许意外的隐式缩小转换。只有当你想要显式缩小时,才使用()而不是{}。

这基本上让我想到了一个相关的问题。我应该选择以下四个替代方案中的哪一个?

bool priority = features(w)[5];

auto priority = static_cast<bool>(features(w)[5]);

auto priority = bool(features(w)[5]);

auto priority = bool{features(w)[5]};

头号仍然是我的最爱。它打字较少,而且与其他三个一样明确。

关于保证初始化的观点并不真正成立,因为我在不知何故之前宣布变量之前不能以某种方式初始化它们。关于缩小的另一个论点在快速测试中没有成功(见http://ideone.com/GXvIIr)。

3 个答案:

答案 0 :(得分:15)

我没有把这本书放在我面前,所以我无法判断是否有更多的背景。

但是要回答你的问题,不,在这个特定的例子中使用auto + static_cast并不是一个好的解决方案。它违反了另一条准则(我从未见过任何例外情况):

  • 尽可能使用最弱的演员/转换。

不必要的强转换会破坏类型系统,并防止编译器生成诊断消息,以防程序中其他地方发生更改,从而以不兼容的方式影响转换。 (远距离行动,维护程序的boogey-man)

此处static_cast不必要地强大。隐式转换会很好。所以避免演员。

答案 1 :(得分:8)

书中的背景:

  

虽然std::vector<bool>概念上保留bool s,但operator[] std::vector<bool>不会返回对容器元素的引用(std::vector::operator[]返回除bool之外的所有类型。相反,它返回一个std::vector<bool>::reference类型的对象(一个嵌套在std::vector<bool>内的类。)

当您使用auto与外部库时,没有任何优势,更多的错误预防。

我认为,这是这种习语的主要思想。你应该明确并强制自动行为正确。

顺便说一句,这里有关于GotW关于自动的好文章。

答案 2 :(得分:3)

  

任何人都可以告诉我,为什么使用这个成语是有利的?

我能想到的原因:因为它是明确的。考虑一下你本能地(本能地)阅读这段代码(即,不知道features做了什么):

bool priority = features(w)[5];

“Features返回一些通用”boolean“值的可索引序列;我们将第五个读入priority”。

auto priority = static_cast<bool>(features(w)[5]);

“功能会返回可显式转换为bool的可转换值序列;我们将第五个值读入priority”。

这段代码不是为了最短的灵活代码而编写的,而是为了显示结果的显式性(显然是一致性的 - 因为我认为它不是唯一用auto声明的变量)。

priority的声明中使用auto是为了使代码对于右侧的任何表达都是灵活的。

那就是说,我更喜欢没有明确演员的版本。