auto和static_casts - 良好的做​​法

时间:2015-10-08 10:08:41

标签: c++ c++11 coding-style

在Scott Meyer的书“Effective Modern C ++”中,我们可以阅读:

std::vector<bool> features(const Widget& w);
Widget w;
…
bool highPriority = features(w)[5];
…
processWidget(w, highPriority); 

和auto

选项
auto highPriority = features(w)[5];

导致未定义的行为,因为features()正在返回std::vector<bool>,在从std::vector<bool>::reference返回值时使用类型为opearator[]的代理对象。 / p>

建议不要停止使用auto,而是使用static_casts来解决此问题。

Scott Meyers建议使用:

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

而不是:

bool highPriority = features(w)[5];

我的问题是: 这两者之间真正的区别是什么?在我看来两者都是相同的,因为两种方法都以完全相同的方式使重构变得更难(在函数功能中改变返回值类型不会使变量highPriority成为不同的类型)而第二种方法的写入时间更短。

3 个答案:

答案 0 :(得分:7)

如果您不喜欢features的界面,可以隐藏辅助功能中的丑陋

bool is_high_priority(const Widget& w)
{ return features(w)[5]; }

现在你的

auto highPriority = is_high_priority(w);

按预期工作。

答案 1 :(得分:5)

使用features函数返回std::vector<bool>

auto highPriority = features(w)[5];

存储逻辑参考。存储的对象是指不再存在的向量。使用它然后会产生未定义的行为。

取而代之的是

bool const highPriority = features(w)[5];

auto const highPriority = !!features(w)[5];

或者,正如斯科特所建议的那样 - 但根据我的口味,它太冗长了 - 请使用static_cast

存储的对象现在是bool

这三种表达同一声明的方式之间没有功能差异。唯一的区别是不起作用的:在我看来static_cast的不必要的冗长,以及!!可能会从一个常见的编译器中抑制关于性能的愚蠢警告。

答案 2 :(得分:0)

当你使用auto时,auto会将它推断为highPriority返回的类型,它是对bool的引用。问题是,highPriority不会返回对bool的引用,而是返回对std :: vector :: reference对象的引用。 (&#39; reference&#39;是std :: vector中的嵌套类)。 std :: vector :: reference是一个&#34;代理类&#34;,一个模拟其他类型行为的类。它不仅是一个代理类,而且是一个不可见的&#34;代理类。这些类与auto不兼容。 Auto无法正确推断出不可见代理类的类型。但是static_cast强制将高优先级转换为bool。这可以避免未定义的行为。