我最近从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)。
答案 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是为了使代码对于右侧的任何表达都是灵活的。
那就是说,我更喜欢没有明确演员的版本。